@mohasinac/appkit 3.3.2 → 3.3.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.
Files changed (46) hide show
  1. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +1 -1
  2. package/dist/_internal/server/features/cart/actions.js +1 -1
  3. package/dist/_internal/server/features/lottery/data.d.ts +2 -3
  4. package/dist/_internal/server/features/products/actions.js +1 -1
  5. package/dist/client/api/surface-error.js +6 -6
  6. package/dist/features/admin/components/AdminSectionsView.js +7 -4
  7. package/dist/features/admin/constants/filter-tabs.js +11 -0
  8. package/dist/features/auctions/columns/index.js +1 -1
  9. package/dist/features/auctions/schemas/index.d.ts +2 -2
  10. package/dist/features/auth/hooks/useRBAC.js +6 -1
  11. package/dist/features/blog/columns/index.js +1 -1
  12. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  13. package/dist/features/contact/email.js +0 -1
  14. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  15. package/dist/features/faq/schemas/index.d.ts +4 -4
  16. package/dist/features/forms/Slider.js +4 -1
  17. package/dist/features/forms/Toggle.js +4 -1
  18. package/dist/features/homepage/components/NewsletterBanner.js +1 -1
  19. package/dist/features/layout/BottomActions.js +27 -0
  20. package/dist/features/layout/BottomActionsContext.d.ts +36 -0
  21. package/dist/features/layout/BottomActionsContext.js +36 -0
  22. package/dist/features/orders/schemas/index.d.ts +2 -2
  23. package/dist/features/payments/schemas/index.d.ts +4 -4
  24. package/dist/features/products/repository/products.repository.js +1 -1
  25. package/dist/features/products/schemas/product-features.validators.d.ts +6 -6
  26. package/dist/features/promotions/repository/claimed-coupons.repository.js +1 -1
  27. package/dist/features/reviews/columns/index.js +1 -1
  28. package/dist/features/search/schemas/index.d.ts +2 -2
  29. package/dist/features/seller/actions/seller-actions.d.ts +2 -2
  30. package/dist/features/seller/components/SellerOrdersView.js +4 -1
  31. package/dist/features/seller/components/SellerProductsView.js +35 -31
  32. package/dist/features/seller/components/SellerReviewsView.js +1 -1
  33. package/dist/features/seller/schemas/index.d.ts +2 -2
  34. package/dist/features/stores/columns/index.js +1 -1
  35. package/dist/features/stores/components/StoresIndexListing.js +20 -15
  36. package/dist/features/support/schemas/index.d.ts +2 -2
  37. package/dist/features/wishlist/actions/wishlist-actions.js +1 -1
  38. package/dist/next/components/NotFoundView.js +17 -0
  39. package/dist/next/components/UnauthorizedView.js +13 -0
  40. package/dist/schemas/registry.d.ts +145 -146
  41. package/dist/schemas/webhooks/razorpay.d.ts +136 -136
  42. package/dist/ui/columns/column-renderers.js +1 -1
  43. package/dist/ui/components/Accordion.js +10 -6
  44. package/dist/ui/components/ListingLayout.js +6 -2
  45. package/dist/validation/schemas.d.ts +4 -4
  46. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
- import { Stack, Text, Heading, Badge, Section, Container, DataTable, } from "../../../../ui";
3
+ import { Stack, Text, Heading, Badge, Section, Container, DataTable } from "../../../../ui";
4
4
  /**
5
5
  * Admin-only view showing slots with price + weight + % chance.
6
6
  * Separate from LotterySlotGrid (public) which never shows price/weight.
@@ -2,7 +2,7 @@
2
2
  import { wrapAction } from "@mohasinac/appkit/server";
3
3
  import { cartRepository } from "../../../../repositories";
4
4
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
- import { addToCartSchema, removeFromCartSchema, mergeGuestCartSchema, } from "../../../shared/features/cart/schema";
5
+ import { addToCartSchema, removeFromCartSchema, mergeGuestCartSchema } from "../../../shared/features/cart/schema";
6
6
  import { upsertCartItem, mergeGuestItems } from "./service";
7
7
  import { ValidationError } from "../../../shared/errors/index";
8
8
  export async function addToCartAction(input) {
@@ -1,6 +1,5 @@
1
1
  import type { SieveModel } from "../../../../providers/db-firebase";
2
2
  import type { EventDocument } from "../../../../features/events/schemas/firestore";
3
- import type { LotteryEntryDocument } from "../../../../features/lottery/schemas/firestore";
4
3
  import type { ClientLotteryConfig } from "../../../../features/lottery/types";
5
4
  /** Event shape with lottery config stripped of price/weight. */
6
5
  export type LotteryEventClient = Omit<EventDocument, "lotteryConfig"> & {
@@ -15,6 +14,6 @@ export declare const listLotteryEvents: (opts?: {
15
14
  pageSize?: number;
16
15
  }) => Promise<LotteryEventClient[]>;
17
16
  /** Fetch lottery entries for admin view (includes phone + txId via PII decrypt). */
18
- export declare function getLotteryEntriesForAdmin(sourceType: "event" | "product", sourceId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<LotteryEntryDocument>>;
17
+ export declare function getLotteryEntriesForAdmin(sourceType: "event" | "product", sourceId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<import("../../../..").LotteryEntryDocument>>;
19
18
  /** Fetch lottery entries for a specific user (own entries only). */
20
- export declare function getLotteryEntriesForUser(userId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<LotteryEntryDocument>>;
19
+ export declare function getLotteryEntriesForUser(userId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<import("../../../..").LotteryEntryDocument>>;
@@ -3,7 +3,7 @@ import { wrapAction } from "@mohasinac/appkit/server";
3
3
  import { productRepository } from "../../../../repositories";
4
4
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
5
  import { isAdminUser } from "../../../../features/auth/role-predicates";
6
- import { productInputSchema, productUpdateSchema, auctionInputSchema, preOrderInputSchema, setFeaturedSchema, setStatusSchema, } from "../../../shared/features/products/schema";
6
+ import { productInputSchema, productUpdateSchema, auctionInputSchema, preOrderInputSchema, setFeaturedSchema, setStatusSchema } from "../../../shared/features/products/schema";
7
7
  import { assertProductOwnership, assertStatusTransition } from "./service";
8
8
  import { ValidationError } from "../../../shared/errors/index";
9
9
  export async function createProductAction(input) {
@@ -1,13 +1,13 @@
1
1
  import { isApiError } from "./ApiError";
2
+ import { ApiClientError } from "../../http/ApiClient";
2
3
  import { normalizeError } from "../../errors/normalize";
3
4
  import { getErrorDisplay } from "../../errors/error-display-map";
4
- /** True for `ApiError` instances and for any other thrown error (e.g. the
5
- * lower-level `ApiClientError` from `ApiClient.request()`) that carries the
6
- * same stable `code: string` field — both shapes route through the same
7
- * toast-vs-inline-field-error logic below. */
5
+ /** True for `ApiError` instances and for `ApiClientError` (the lower-level
6
+ * error `ApiClient.request()` throws) when it carries a stable `code` —
7
+ * both shapes route through the same toast-vs-inline-field-error logic
8
+ * below. */
8
9
  function hasStableErrorCode(err) {
9
- return (isApiError(err) ||
10
- (err instanceof Error && typeof err.code === "string"));
10
+ return isApiError(err) || (err instanceof ApiClientError && typeof err.code === "string");
11
11
  }
12
12
  export function surfaceError(err, opts) {
13
13
  const { showToast, setFieldError, translate, report } = opts;
@@ -12,7 +12,7 @@ import { ADMIN_ENDPOINTS, DEMO_ENDPOINTS } from "../../../constants";
12
12
  import { useAdminSectionsListing } from "../hooks/useAdminSectionsListing";
13
13
  import { DataTable } from "./DataTable";
14
14
  import { SECTION_TYPE_OPTIONS, SUPPORTED_TYPED_BUILDERS, RESOURCE_SORT_OPTIONS, FAQ_CATEGORY_OPTIONS, DEFAULT_PRODUCTS_BUILDER, DEFAULT_AUCTIONS_BUILDER, DEFAULT_STATS_BUILDER, DEFAULT_PRE_ORDERS_BUILDER, DEFAULT_STORES_BUILDER, DEFAULT_EVENTS_BUILDER, DEFAULT_SOCIAL_FEED_BUILDER, DEFAULT_WELCOME_BUILDER, DEFAULT_TRUST_INDICATORS_BUILDER, DEFAULT_CATEGORIES_BUILDER, DEFAULT_BRANDS_BUILDER, DEFAULT_BANNER_BUILDER, DEFAULT_FEATURES_BUILDER, DEFAULT_REVIEWS_BUILDER, DEFAULT_WHATSAPP_BUILDER, DEFAULT_FAQ_BUILDER, DEFAULT_BLOG_BUILDER, DEFAULT_NEWSLETTER_BUILDER, DEFAULT_CAROUSEL_BUILDER, DEFAULT_CUSTOM_CARDS_BUILDER, DEFAULT_GOOGLE_REVIEWS_BUILDER, DEFAULT_FEATURED_BUNDLES_BUILDER, DEFAULT_PRIZE_DRAWS_BUILDER, DEFAULT_EVENT_RAFFLES_BUILDER, DEFAULT_COLLECTION_CARDS_BUILDER, } from "./sections/adminSectionsTypes";
15
- import { toStringValue, buildProductsConfig, buildAuctionsConfig, buildStatsConfig, buildPreOrdersConfig, buildStoresConfig, buildEventsConfig, buildSocialFeedConfig, buildWelcomeConfig, buildTrustIndicatorsConfig, buildCategoriesConfig, buildBrandsConfig, buildBannerConfig, buildFeaturesConfig, buildReviewsConfig, buildWhatsAppConfig, buildFAQConfig, buildBlogConfig, buildNewsletterConfig, buildCarouselConfig, buildCustomCardsConfig, buildGoogleReviewsConfig, buildFeaturedBundlesConfig, buildPrizeDrawsConfig, buildEventRafflesConfig, buildCollectionCardsConfig, parseProductsBuilder, parseAuctionsBuilder, parseStatsBuilder, parsePreOrdersBuilder, parseStoresBuilder, parseEventsBuilder, parseSocialFeedBuilder, parseWelcomeBuilder, parseTrustIndicatorsBuilder, parseCategoriesBuilder, parseBrandsBuilder, parseBannerBuilder, parseFeaturesBuilder, parseReviewsBuilder, parseWhatsAppBuilder, parseFAQBuilder, parseBlogBuilder, parseNewsletterBuilder, parseCarouselBuilder, parseCustomCardsBuilder, parseGoogleReviewsBuilder, parseFeaturedBundlesBuilder, parsePrizeDrawsBuilder, parseEventRafflesBuilder, parseCollectionCardsBuilder, } from "./sections/adminSectionsBuildParse";
15
+ import { toStringValue, buildProductsConfig, buildAuctionsConfig, buildStatsConfig, buildPreOrdersConfig, buildStoresConfig, buildEventsConfig, buildSocialFeedConfig, buildWelcomeConfig, buildTrustIndicatorsConfig, buildCategoriesConfig, buildBrandsConfig, buildBannerConfig, buildFeaturesConfig, buildReviewsConfig, buildWhatsAppConfig, buildFAQConfig, buildBlogConfig, buildNewsletterConfig, buildCarouselConfig, buildCustomCardsConfig, buildGoogleReviewsConfig, buildFeaturedBundlesConfig, buildPrizeDrawsConfig, buildEventRafflesConfig, buildCollectionCardsConfig, parseProductsBuilder, parseAuctionsBuilder, parseStatsBuilder, parsePreOrdersBuilder, parseStoresBuilder, parseEventsBuilder, parseSocialFeedBuilder, parseWelcomeBuilder, parseTrustIndicatorsBuilder, parseCategoriesBuilder, parseBrandsBuilder, parseBannerBuilder, parseFeaturesBuilder, parseReviewsBuilder, parseWhatsAppBuilder, parseFAQBuilder, parseBlogBuilder, parseNewsletterBuilder, parseCarouselBuilder, parseCustomCardsBuilder, parseGoogleReviewsBuilder, parseFeaturedBundlesBuilder, parsePrizeDrawsBuilder, parseEventRafflesBuilder, parseCollectionCardsBuilder } from "./sections/adminSectionsBuildParse";
16
16
  const __P = {
17
17
  p3: "p-3",
18
18
  p4: "p-4",
@@ -944,6 +944,12 @@ export function AdminSectionsView({ children }) {
944
944
  default: return null;
945
945
  }
946
946
  }
947
+ // React.useMemo must run unconditionally on every render — it was
948
+ // previously declared after the `hasChildren` early return below, which
949
+ // skips the hook call in passthrough mode, violating the Rules of Hooks.
950
+ const sectionOrderMap = React.useMemo(() => {
951
+ return new Map(sections.map((section) => [section.id, section.order]));
952
+ }, [sections]);
947
953
  // If children exist, render passthrough mode (detail view)
948
954
  if (hasChildren) {
949
955
  return _jsx(_Fragment, { children: children });
@@ -956,9 +962,6 @@ export function AdminSectionsView({ children }) {
956
962
  status: section.enabled ? "Active" : "Inactive",
957
963
  updatedAt: new Date(section.updatedAt).toLocaleDateString(),
958
964
  }));
959
- const sectionOrderMap = React.useMemo(() => {
960
- return new Map(sections.map((section) => [section.id, section.order]));
961
- }, [sections]);
962
965
  const hasReorderChanges = reorderDraft.some((item) => sectionOrderMap.get(item.id) !== item.order);
963
966
  const canUndoReorderChanges = reorderUndoStack.length > 0;
964
967
  return (_jsxs(_Fragment, { children: [_jsxs(Div, { paddingX: "x-sm-md", padding: "y-md", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "3", children: [_jsxs(Div, { children: [_jsx(Text, { size: "base", weight: "semibold", color: "primary", children: "Homepage Sections" }), _jsx(Text, { size: "sm", color: "muted", children: "Manage homepage sections and their display order" })] }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setSeedResetOpen(true), children: "Reset seed data" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => setIsModalOpen(true), children: "Manage Sections" })] })] }), errorMessage && (_jsx(Div, { textSize: "sm", className: "mb-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "xl", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No sections found" })] }), _jsxs(Stack, { className: `mt-4 ${__P.p4}`, gap: "3", rounded: "xl", surface: "default", border: "default", children: [_jsxs(Row, { align: "center", justify: "between", gap: "3", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Reorder Sections" }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: reindexDraft, disabled: reorderSections.isPending || reorderDraft.length === 0, children: "Reindex 1..N" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: undoReorderChange, disabled: reorderSections.isPending || !canUndoReorderChanges, children: "Undo unsaved" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: resetToServerOrder, disabled: reorderSections.isPending || !hasReorderChanges, children: "Reset to server" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: () => reorderSections.mutate(), disabled: !hasReorderChanges || reorderSections.isPending, children: reorderSections.isPending ? "Saving order..." : "Save order" })] })] }), reorderDraft.length === 0 ? (_jsx(Text, { size: "sm", color: "muted", children: "No sections to reorder." })) : (_jsx(Stack, { gap: "sm", children: reorderDraft.map((item, index) => (_jsxs(Div, { layout: "grid", gap: "2", align: "center", className: "grid-cols-[auto_1fr_auto_auto_auto]", rounded: "md", padding: "xs", border: "default", draggable: true, onDragStart: () => setDragIndex(index), onDragOver: (event) => event.preventDefault(), onDrop: () => handleReorderDrop(index), onDragEnd: () => setDragIndex(null), children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "\u2261" }), _jsxs(Text, { size: "sm", color: "primary", children: [item.type, " #", item.order] }), _jsx(Input, { type: "number", min: 1, max: reorderDraft.length, value: String(item.order), onChange: (event) => updateReorderItemOrder(index, Number(event.target.value) || 1), className: "w-24" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => moveReorderItem(index, -1), disabled: index === 0, children: "Up" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => moveReorderItem(index, 1), disabled: index === reorderDraft.length - 1, children: "Down" })] }, `reorder-${item.id}`))) }))] }), _jsx(ConfirmDeleteModal, { isOpen: seedResetOpen, onClose: () => setSeedResetOpen(false), onConfirm: () => resetSeed.mutate(), title: "Reset homepage sections seed data?", message: "This will reload the 19 default homepage sections from seed data. Any manual changes made in Firestore will be overwritten.", confirmText: "Reset seed", cancelText: "Cancel", isDeleting: resetSeed.isPending, variant: "danger" }), _jsx(Modal, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), title: "Manage Homepage Section", size: "lg", children: _jsxs(Form, { onSubmit: (event) => {
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Admin filter-chip tab sets (SB10-C completion, S8 2026-05-13).
3
+ *
4
+ * Match current view-filter values exactly so migrating an inline
5
+ * `STATUS_OPTIONS` array to one of these constants is a behaviour-preserving
6
+ * rename. The `ALL_TAB` sentinel collapses to an empty filter string when
7
+ * clicked.
8
+ *
9
+ * Each entry is a typed `{ id, label }` row so views render with one
10
+ * primitive and stay in sync when statuses are added.
11
+ */
1
12
  export const ALL_TAB = { id: "All", label: "All" };
2
13
  /** Admin > Products — listing status filter chip set. */
3
14
  export const ADMIN_PRODUCT_STATUS_TABS = [
@@ -1,4 +1,4 @@
1
- import { buildColumns, } from "../../../ui/columns";
1
+ import { buildColumns } from "../../../ui/columns";
2
2
  // --- Auction columns ----------------------------------------------------------
3
3
  /**
4
4
  * Default admin column definitions for an auction table.
@@ -58,8 +58,8 @@ export declare const auctionItemSchema: z.ZodObject<{
58
58
  createdAt: z.ZodString;
59
59
  updatedAt: z.ZodString;
60
60
  }, "strip", z.ZodTypeAny, {
61
- status: "draft" | "published" | "archived" | "sold";
62
61
  currency: string;
62
+ status: "draft" | "published" | "archived" | "sold";
63
63
  featured: boolean;
64
64
  listingType: "auction";
65
65
  createdAt: string;
@@ -87,8 +87,8 @@ export declare const auctionItemSchema: z.ZodObject<{
87
87
  }[] | undefined;
88
88
  storeSlug?: string | undefined;
89
89
  }, {
90
- status: "draft" | "published" | "archived" | "sold";
91
90
  currency: string;
91
+ status: "draft" | "published" | "archived" | "sold";
92
92
  featured: boolean;
93
93
  listingType: "auction";
94
94
  createdAt: string;
@@ -51,9 +51,14 @@ export function useRoleChecks() {
51
51
  }
52
52
  export function useIsOwner(resourceOwnerId) {
53
53
  const { user } = useCurrentUser();
54
+ // useHasRole must run unconditionally on every render — it was previously
55
+ // called after the early return below, which skips the hook call whenever
56
+ // !user || !resourceOwnerId, violating the Rules of Hooks (call-count
57
+ // mismatch risk when that condition flips between renders).
58
+ const isAdmin = useHasRole("admin");
54
59
  if (!user || !resourceOwnerId)
55
60
  return false;
56
- if (useHasRole("admin"))
61
+ if (isAdmin)
57
62
  return true;
58
63
  return user.id === resourceOwnerId;
59
64
  }
@@ -1,4 +1,4 @@
1
- import { buildColumns, } from "../../../ui/columns";
1
+ import { buildColumns } from "../../../ui/columns";
2
2
  /**
3
3
  * Default admin column definitions for a blog post table.
4
4
  *
@@ -194,7 +194,7 @@ export declare const categoryQueryHelpers: {
194
194
  /** @deprecated Use byCategoryType("brand"). */
195
195
  readonly brands: () => readonly ["isBrand", "==", true];
196
196
  /** SB-UNI B + C + D — discriminator-based listing. */
197
- readonly byCategoryType: (type: import("../types").CategoryType) => readonly ["categoryType", "==", import("@mohasinac/appkit").CategoryType];
197
+ readonly byCategoryType: (type: import("../types").CategoryType) => readonly ["categoryType", "==", import("..").CategoryType];
198
198
  readonly sublistings: () => readonly ["categoryType", "==", "sublisting"];
199
199
  readonly brandPages: () => readonly ["categoryType", "==", "brand"];
200
200
  readonly active: () => readonly ["isActive", "==", true];
@@ -8,7 +8,6 @@ import "server-only";
8
8
  // → providers.config.ts → @mohasinac/appkit/server → ... → email.tsx).
9
9
  // `require()` is opaque to Next's static analyser so the chain stops here.
10
10
  function renderToStaticMarkup(el) {
11
- // eslint-disable-next-line @typescript-eslint/no-require-imports
12
11
  const m = require("react-dom/server");
13
12
  return m.renderToStaticMarkup(el);
14
13
  }
@@ -27,8 +27,8 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
27
27
  template: z.ZodOptional<z.ZodString>;
28
28
  }, "strip", z.ZodTypeAny, {
29
29
  category: string;
30
- order: number;
31
30
  priority: number;
31
+ order: number;
32
32
  isActive: boolean;
33
33
  question: string;
34
34
  showOnHomepage: boolean;
@@ -51,9 +51,9 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
51
51
  format?: "html" | "plain" | "markdown" | undefined;
52
52
  };
53
53
  tags?: string[] | undefined;
54
+ priority?: number | undefined;
54
55
  template?: string | undefined;
55
56
  order?: number | undefined;
56
- priority?: number | undefined;
57
57
  isActive?: boolean | undefined;
58
58
  variables?: Record<string, string> | undefined;
59
59
  showOnHomepage?: boolean | undefined;
@@ -63,8 +63,8 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
63
63
  useSiteSettings?: boolean | undefined;
64
64
  }>, {
65
65
  category: string;
66
- order: number;
67
66
  priority: number;
67
+ order: number;
68
68
  isActive: boolean;
69
69
  question: string;
70
70
  showOnHomepage: boolean;
@@ -87,9 +87,9 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
87
87
  format?: "html" | "plain" | "markdown" | undefined;
88
88
  };
89
89
  tags?: string[] | undefined;
90
+ priority?: number | undefined;
90
91
  template?: string | undefined;
91
92
  order?: number | undefined;
92
- priority?: number | undefined;
93
93
  isActive?: boolean | undefined;
94
94
  variables?: Record<string, string> | undefined;
95
95
  showOnHomepage?: boolean | undefined;
@@ -125,9 +125,9 @@ export declare const faqUpdateSchema: z.ZodObject<{
125
125
  }, "strip", z.ZodTypeAny, {
126
126
  category?: string | undefined;
127
127
  tags?: string[] | undefined;
128
+ priority?: number | undefined;
128
129
  template?: string | undefined;
129
130
  order?: number | undefined;
130
- priority?: number | undefined;
131
131
  isActive?: boolean | undefined;
132
132
  variables?: Record<string, string> | undefined;
133
133
  question?: string | undefined;
@@ -143,9 +143,9 @@ export declare const faqUpdateSchema: z.ZodObject<{
143
143
  }, {
144
144
  category?: string | undefined;
145
145
  tags?: string[] | undefined;
146
+ priority?: number | undefined;
146
147
  template?: string | undefined;
147
148
  order?: number | undefined;
148
- priority?: number | undefined;
149
149
  isActive?: boolean | undefined;
150
150
  variables?: Record<string, string> | undefined;
151
151
  question?: string | undefined;
@@ -92,8 +92,8 @@ export declare const faqSchema: z.ZodObject<{
92
92
  createdAt?: string | undefined;
93
93
  tags?: string[] | undefined;
94
94
  updatedAt?: string | undefined;
95
- order?: number | undefined;
96
95
  priority?: number | undefined;
96
+ order?: number | undefined;
97
97
  stats?: {
98
98
  views?: number | undefined;
99
99
  helpful?: number | undefined;
@@ -118,8 +118,8 @@ export declare const faqSchema: z.ZodObject<{
118
118
  createdAt?: string | undefined;
119
119
  tags?: string[] | undefined;
120
120
  updatedAt?: string | undefined;
121
- order?: number | undefined;
122
121
  priority?: number | undefined;
122
+ order?: number | undefined;
123
123
  stats?: {
124
124
  views?: number | undefined;
125
125
  helpful?: number | undefined;
@@ -283,8 +283,8 @@ export declare const faqFirestoreSchema: z.ZodObject<{
283
283
  updatedAt: string | Date | z.objectOutputType<{
284
284
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
285
285
  }, z.ZodTypeAny, "passthrough">;
286
- order: number;
287
286
  priority: number;
287
+ order: number;
288
288
  stats: {
289
289
  views: number;
290
290
  helpful: number;
@@ -322,8 +322,8 @@ export declare const faqFirestoreSchema: z.ZodObject<{
322
322
  updatedAt: string | Date | z.objectInputType<{
323
323
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
324
324
  }, z.ZodTypeAny, "passthrough">;
325
- order: number;
326
325
  priority: number;
326
+ order: number;
327
327
  stats: {
328
328
  views: number;
329
329
  helpful: number;
@@ -9,7 +9,10 @@ import { cn, LABEL_BASE, ERROR_BASE } from "./utils";
9
9
  export function Slider({ value: controlledValue, defaultValue = 0, min = 0, max = 100, step = 1, onChange, label, error, disabled = false, showValue = true, formatValue, className = "", id, }) {
10
10
  const [internalValue, setInternalValue] = React.useState(defaultValue);
11
11
  const value = controlledValue !== undefined ? controlledValue : internalValue;
12
- const sliderId = id ?? React.useId();
12
+ // React.useId() must run unconditionally on every render — using `id ?? React.useId()`
13
+ // skips the hook call whenever `id` is provided, violating the Rules of Hooks.
14
+ const generatedId = React.useId();
15
+ const sliderId = id ?? generatedId;
13
16
  const pct = ((value - min) / (max - min)) * 100;
14
17
  const fillRef = useRef(null);
15
18
  useEffect(() => {
@@ -38,7 +38,10 @@ export function Toggle({ checked: controlledChecked, defaultChecked = false, onC
38
38
  setInternalChecked(newChecked);
39
39
  onChange?.(newChecked);
40
40
  };
41
- const toggleId = id ?? React.useId();
41
+ // React.useId() must run unconditionally on every render — using `id ?? React.useId()`
42
+ // skips the hook call whenever `id` is provided, violating the Rules of Hooks.
43
+ const generatedId = React.useId();
44
+ const toggleId = id ?? generatedId;
42
45
  const cfg = SIZE_CONFIG[size];
43
46
  return (_jsxs(Row, { className: cn("gap-3", className), children: [_jsx(Button, { type: "button", role: "switch", id: toggleId, "aria-checked": checked, disabled: disabled, onClick: handleChange, className: cn("relative inline-flex items-center rounded-full transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary-500/30 dark:focus:ring-secondary-400/30 focus:ring-offset-2 dark:focus:ring-offset-slate-900", cfg.track, checked
44
47
  ? "bg-primary-600 dark:bg-secondary-500"
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
4
  import { useState } from "react";
5
- import { Button, Div, Heading, Span, Text, } from "../../../ui";
5
+ import { Button, Div, Heading, Span, Text } from "../../../ui";
6
6
  import { DynamicBgDiv } from "../../../ui/components/DynamicBgDiv";
7
7
  import { Form } from "../../../ui/components/Form";
8
8
  import { FieldInput } from "../../../ui/forms/FieldInput";
@@ -1,5 +1,32 @@
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 sieveFilter("bulk.selectedCount", SIEVE_OP.GT, "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
+ */
3
30
  import { useState, useRef, useEffect } from "react";
4
31
  import { X, ChevronUp, ChevronDown, Check } from "lucide-react";
5
32
  import { useBottomActionsContext } from "./BottomActionsContext";
@@ -1,3 +1,39 @@
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 sieveFilter("bulk.selectedCount", SIEVE_OP.GT, "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
+ */
1
37
  import React from "react";
2
38
  import type { ButtonProps } from "../../ui";
3
39
  export interface BottomAction {
@@ -1,5 +1,41 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * BottomActionsContext
5
+ *
6
+ * Provides a context for registering page-level mobile action bars.
7
+ * Features call `useBottomActions` to push actions; the `<BottomActions>`
8
+ * layout component reads this context and renders the bar above BottomNavbar.
9
+ *
10
+ * Supports two modes:
11
+ * - Page mode: primary page actions (Add to Cart, Buy Now, Place Bid, etc.)
12
+ * - Bulk mode: activated when sieveFilter("bulk.selectedCount", SIEVE_OP.GT, "0") — shows selection
13
+ * count + custom bulk action buttons (Delete, Archive, Export, etc.)
14
+ *
15
+ * @example — product detail page
16
+ * ```tsx
17
+ * useBottomActions({
18
+ * actions: [
19
+ * { id: "wishlist", icon: <Heart className="w-4 h-4" />, label: t("wishlist"), variant: "ghost", grow: false, onClick: handleWishlist },
20
+ * { id: "cart", label: t("addToCart"), variant: "outline", onClick: handleAddToCart },
21
+ * { id: "buy", label: t("buyNow"), variant: "primary", onClick: handleBuyNow },
22
+ * ],
23
+ * });
24
+ * ```
25
+ *
26
+ * @example — admin listing with bulk select
27
+ * ```tsx
28
+ * useBottomActions({
29
+ * bulk: {
30
+ * selectedCount: selectedIds.length,
31
+ * onClearSelection: () => setSelectedIds([]),
32
+ * actions: [
33
+ * { id: "delete", label: t("bulkDelete", { count: selectedIds.length }), variant: "danger", onClick: handleBulkDelete },
34
+ * ],
35
+ * },
36
+ * });
37
+ * ```
38
+ */
3
39
  import { createContext, useCallback, useContext, useMemo, useRef, useState, } from "react";
4
40
  const EMPTY = { actions: [] };
5
41
  const BottomActionsContext = createContext(null);
@@ -521,8 +521,8 @@ export declare const orderFirestoreSchema: z.ZodObject<{
521
521
  bin: string;
522
522
  }>>;
523
523
  }, "strip", z.ZodTypeAny, {
524
- status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
525
524
  currency: string;
525
+ status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
526
526
  createdAt: string | Date | z.objectOutputType<{
527
527
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
528
528
  }, z.ZodTypeAny, "passthrough">;
@@ -666,8 +666,8 @@ export declare const orderFirestoreSchema: z.ZodObject<{
666
666
  }, z.ZodTypeAny, "passthrough"> | undefined;
667
667
  shippingProofUploadedBy?: string | undefined;
668
668
  }, {
669
- status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
670
669
  currency: string;
670
+ status: "cancelled" | "pending" | "processing" | "refunded" | "confirmed" | "shipped" | "delivered" | "return_requested" | "returned";
671
671
  createdAt: string | Date | z.objectInputType<{
672
672
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
673
673
  }, z.ZodTypeAny, "passthrough">;
@@ -150,8 +150,8 @@ export declare const payoutFirestoreSchema: z.ZodObject<{
150
150
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
151
151
  }, z.ZodTypeAny, "passthrough">>]>>;
152
152
  }, "strip", z.ZodTypeAny, {
153
- status: "pending" | "paid" | "failed" | "processing";
154
153
  currency: string;
154
+ status: "pending" | "paid" | "failed" | "processing";
155
155
  storeId: string;
156
156
  createdAt: string | Date | z.objectOutputType<{
157
157
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
@@ -200,8 +200,8 @@ export declare const payoutFirestoreSchema: z.ZodObject<{
200
200
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
201
201
  }, z.ZodTypeAny, "passthrough"> | undefined;
202
202
  }, {
203
- status: "pending" | "paid" | "failed" | "processing";
204
203
  currency: string;
204
+ status: "pending" | "paid" | "failed" | "processing";
205
205
  storeId: string;
206
206
  createdAt: string | Date | z.objectInputType<{
207
207
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
@@ -289,8 +289,8 @@ export declare const paymentRecordSchema: z.ZodObject<{
289
289
  status: z.ZodDefault<z.ZodEnum<["pending", "authorized", "captured", "failed", "refunded", "partially_refunded"]>>;
290
290
  createdAt: z.ZodOptional<z.ZodString>;
291
291
  }, "strip", z.ZodTypeAny, {
292
- status: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded";
293
292
  currency: string;
293
+ status: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded";
294
294
  id: string;
295
295
  amount: number;
296
296
  orderId: string;
@@ -302,8 +302,8 @@ export declare const paymentRecordSchema: z.ZodObject<{
302
302
  amount: number;
303
303
  orderId: string;
304
304
  gateway: "bank_transfer" | "upi" | "razorpay" | "stripe" | "paypal" | "cod" | "whatsapp";
305
- status?: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded" | undefined;
306
305
  currency?: string | undefined;
306
+ status?: "pending" | "failed" | "captured" | "authorized" | "refunded" | "partially_refunded" | undefined;
307
307
  createdAt?: string | undefined;
308
308
  gatewayPaymentId?: string | undefined;
309
309
  }>;
@@ -4,7 +4,7 @@ import { DatabaseError } from "../../../errors";
4
4
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
5
5
  import { cacheManager } from "../../../core";
6
6
  import { generateUniqueId, slugify, buildSearchTokens, tokenizeQuery, generateBarcodeId } from "../../../utils";
7
- import { PRODUCT_COLLECTION, ProductStatusValues, } from "../schemas";
7
+ import { PRODUCT_COLLECTION, ProductStatusValues } from "../schemas";
8
8
  import { PRODUCT_FIELDS } from "../../../constants/field-names";
9
9
  /**
10
10
  * Canonical listing-kind tokens used in `listingType`. Note: the public Sieve
@@ -22,7 +22,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
22
22
  isActive: z.ZodBoolean;
23
23
  displayOrder: z.ZodNumber;
24
24
  }, "strip", z.ZodTypeAny, {
25
- category: "custom" | "seller" | "auction" | "condition" | "shipping" | "preorder" | "platform";
25
+ category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
26
26
  label: string;
27
27
  scope: "store" | "platform";
28
28
  icon: string;
@@ -33,7 +33,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
33
33
  description?: string | undefined;
34
34
  iconColor?: string | undefined;
35
35
  }, {
36
- category: "custom" | "seller" | "auction" | "condition" | "shipping" | "preorder" | "platform";
36
+ category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
37
37
  label: string;
38
38
  scope: "store" | "platform";
39
39
  icon: string;
@@ -55,7 +55,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
55
55
  isActive: z.ZodBoolean;
56
56
  displayOrder: z.ZodNumber;
57
57
  }, "strip", z.ZodTypeAny, {
58
- category: "custom" | "seller" | "auction" | "condition" | "shipping" | "preorder" | "platform";
58
+ category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
59
59
  label: string;
60
60
  icon: string;
61
61
  isActive: boolean;
@@ -64,7 +64,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
64
64
  description?: string | undefined;
65
65
  iconColor?: string | undefined;
66
66
  }, {
67
- category: "custom" | "seller" | "auction" | "condition" | "shipping" | "preorder" | "platform";
67
+ category: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform";
68
68
  label: string;
69
69
  icon: string;
70
70
  isActive: boolean;
@@ -84,7 +84,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
84
84
  isActive: z.ZodOptional<z.ZodBoolean>;
85
85
  displayOrder: z.ZodOptional<z.ZodNumber>;
86
86
  }, "strip", z.ZodTypeAny, {
87
- category?: "custom" | "seller" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
87
+ category?: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
88
88
  description?: string | undefined;
89
89
  label?: string | undefined;
90
90
  icon?: string | undefined;
@@ -93,7 +93,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
93
93
  iconColor?: string | undefined;
94
94
  productTypes?: ("auction" | "prize-draw" | "classified" | "digital-code" | "live" | "all" | "product" | "preorder")[] | undefined;
95
95
  }, {
96
- category?: "custom" | "seller" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
96
+ category?: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
97
97
  description?: string | undefined;
98
98
  label?: string | undefined;
99
99
  icon?: string | undefined;
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
9
9
  import { normalizeError } from "../../../errors/normalize";
10
- import { CLAIMED_COUPONS_COLLECTION, createClaimedCouponId, } from "../schemas";
10
+ import { CLAIMED_COUPONS_COLLECTION, createClaimedCouponId } from "../schemas";
11
11
  import { DatabaseError } from "../../../errors";
12
12
  import { COUPON_USAGE_FIELDS } from "../../../constants/field-names";
13
13
  export class ClaimedCouponsRepository extends BaseRepository {
@@ -1,4 +1,4 @@
1
- import { buildColumns, } from "../../../ui/columns";
1
+ import { buildColumns } from "../../../ui/columns";
2
2
  /**
3
3
  * Default admin column definitions for a review table.
4
4
  *
@@ -24,8 +24,8 @@ export declare const searchProductItemSchema: z.ZodObject<{
24
24
  title: string;
25
25
  slug: string;
26
26
  id: string;
27
- status?: string | undefined;
28
27
  currency?: string | undefined;
28
+ status?: string | undefined;
29
29
  featured?: boolean | undefined;
30
30
  listingType?: "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | undefined;
31
31
  isPromoted?: boolean | undefined;
@@ -35,8 +35,8 @@ export declare const searchProductItemSchema: z.ZodObject<{
35
35
  title: string;
36
36
  slug: string;
37
37
  id: string;
38
- status?: string | undefined;
39
38
  currency?: string | undefined;
39
+ status?: string | undefined;
40
40
  featured?: boolean | undefined;
41
41
  listingType?: "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | undefined;
42
42
  isPromoted?: boolean | undefined;