@mohasinac/appkit 2.7.16 → 2.7.18

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 (105) hide show
  1. package/dist/_internal/server/features/auctions/actions.js +1 -1
  2. package/dist/_internal/server/features/blog/actions.js +2 -2
  3. package/dist/_internal/server/features/brands/actions.js +2 -2
  4. package/dist/_internal/server/features/bundles/actions.d.ts +15 -0
  5. package/dist/_internal/server/features/bundles/actions.js +48 -0
  6. package/dist/_internal/server/features/bundles/index.d.ts +1 -0
  7. package/dist/_internal/server/features/bundles/index.js +1 -0
  8. package/dist/_internal/server/features/cart/actions.js +3 -3
  9. package/dist/_internal/server/features/checkout/actions.d.ts +4 -0
  10. package/dist/_internal/server/features/checkout/actions.js +23 -12
  11. package/dist/_internal/server/features/events/actions.js +3 -3
  12. package/dist/_internal/server/features/orders/actions.js +4 -4
  13. package/dist/_internal/server/features/payments/data.d.ts +5 -3
  14. package/dist/_internal/server/features/payments/data.js +13 -8
  15. package/dist/_internal/server/features/payments/index.d.ts +1 -1
  16. package/dist/_internal/server/features/payments/index.js +1 -1
  17. package/dist/_internal/server/features/pre-orders/actions.js +1 -1
  18. package/dist/_internal/server/features/products/actions.js +6 -6
  19. package/dist/_internal/server/features/promotions/actions.js +3 -3
  20. package/dist/_internal/shared/features/categories/bundle-config.d.ts +24 -0
  21. package/dist/_internal/shared/features/categories/bundle-config.js +28 -0
  22. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +7 -0
  23. package/dist/_internal/shared/features/categories/bundle-copy.js +9 -0
  24. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +69 -19
  25. package/dist/_internal/shared/features/categories/bundle-schemas.js +20 -2
  26. package/dist/_internal/shared/features/checkout/config.d.ts +1 -1
  27. package/dist/_internal/shared/features/checkout/config.js +1 -1
  28. package/dist/_internal/shared/features/payments/config.d.ts +2 -1
  29. package/dist/_internal/shared/features/payments/config.js +2 -1
  30. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  31. package/dist/constants/field-names.d.ts +8 -1
  32. package/dist/constants/field-names.js +9 -2
  33. package/dist/constants/table-keys.d.ts +3 -0
  34. package/dist/constants/table-keys.js +3 -0
  35. package/dist/features/admin/components/AdminSiteSettingsView.js +17 -15
  36. package/dist/features/admin/components/DashboardStats.js +20 -12
  37. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +18 -2
  38. package/dist/features/admin/components/analytics/AdminStatCard.d.ts +7 -1
  39. package/dist/features/admin/components/analytics/AdminStatCard.js +13 -2
  40. package/dist/features/admin/schemas/firestore.d.ts +18 -4
  41. package/dist/features/admin/schemas/firestore.js +11 -1
  42. package/dist/features/categories/components/BundleBuyNowCta.d.ts +3 -1
  43. package/dist/features/categories/components/BundleBuyNowCta.js +3 -3
  44. package/dist/features/categories/components/BundleDynamicRuleEditor.d.ts +1 -1
  45. package/dist/features/categories/components/BundleDynamicRuleEditor.js +2 -1
  46. package/dist/features/categories/components/BundlesListView.d.ts +4 -1
  47. package/dist/features/categories/components/BundlesListView.js +2 -2
  48. package/dist/features/categories/components/CategoryBundlesListing.d.ts +4 -1
  49. package/dist/features/categories/components/CategoryBundlesListing.js +9 -8
  50. package/dist/features/categories/schemas/firestore.d.ts +29 -1
  51. package/dist/features/checkout/actions/checkout-actions.d.ts +11 -0
  52. package/dist/features/checkout/actions/checkout-actions.js +26 -0
  53. package/dist/features/filters/FilterFacetSection.d.ts +6 -1
  54. package/dist/features/filters/FilterFacetSection.js +25 -2
  55. package/dist/features/homepage/components/FeaturedBundlesSection.d.ts +4 -1
  56. package/dist/features/homepage/components/FeaturedBundlesSection.js +9 -8
  57. package/dist/features/orders/actions/refund-actions.js +10 -7
  58. package/dist/features/orders/schemas/firestore.d.ts +16 -13
  59. package/dist/features/orders/schemas/firestore.js +6 -5
  60. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
  61. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +2 -1
  62. package/dist/features/products/components/AuctionsIndexListing.js +2 -1
  63. package/dist/features/products/components/ProductDetailPageView.js +3 -1
  64. package/dist/features/products/components/ProductDetailView.d.ts +3 -1
  65. package/dist/features/products/components/ProductDetailView.js +2 -2
  66. package/dist/features/products/components/ProductFilters.d.ts +10 -4
  67. package/dist/features/products/components/ProductFilters.js +20 -16
  68. package/dist/features/products/components/ProductGrid.js +3 -3
  69. package/dist/features/products/components/ProductsIndexListing.js +2 -1
  70. package/dist/features/products/constants/product-features.constants.js +5 -1
  71. package/dist/features/products/schemas/index.d.ts +2 -2
  72. package/dist/features/products/schemas/product-features.d.ts +1 -1
  73. package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
  74. package/dist/features/products/schemas/product-features.validators.js +4 -0
  75. package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
  76. package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +10 -4
  77. package/dist/features/shell/FormShell.js +1 -1
  78. package/dist/features/stores/components/StoreBundlesPageView.d.ts +4 -1
  79. package/dist/features/stores/components/StoreBundlesPageView.js +2 -2
  80. package/dist/features/stores/components/StoresIndexListing.js +2 -1
  81. package/dist/features/wishlist/hooks/useWishlistCount.d.ts +2 -2
  82. package/dist/features/wishlist/hooks/useWishlistCount.js +5 -8
  83. package/dist/providers/db-firebase/admin-app-lite.js +8 -2
  84. package/dist/providers/db-firebase/admin.js +8 -2
  85. package/dist/seed/addresses-seed-data.js +24 -7
  86. package/dist/seed/cart-seed-data.d.ts +10 -10
  87. package/dist/seed/cart-seed-data.js +39 -2
  88. package/dist/seed/grouped-listings-seed-data.js +47 -0
  89. package/dist/seed/orders-seed-data.js +150 -0
  90. package/dist/seed/products-standard-seed-data.js +42 -0
  91. package/dist/seed/site-settings-seed-data.js +11 -4
  92. package/dist/seed/users-seed-data.js +1 -1
  93. package/dist/seed/wishlists-seed-data.js +7 -0
  94. package/dist/server-entry.d.ts +2 -1
  95. package/dist/server-entry.js +2 -1
  96. package/dist/server.d.ts +2 -1
  97. package/dist/server.js +3 -1
  98. package/dist/tailwind-utilities.css +1 -1
  99. package/dist/ui/components/Breadcrumb.style.css +1 -1
  100. package/dist/ui/components/ListingLayout.style.css +1 -1
  101. package/dist/ui/components/Select.style.css +1 -1
  102. package/dist/ui/components/SideDrawer.style.css +55 -12
  103. package/dist/ui/components/Typography.style.css +2 -2
  104. package/dist/ui/rich-text/RichText.style.css +4 -5
  105. package/package.json +1 -1
@@ -49,7 +49,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
49
49
  .filter(Boolean)
50
50
  .join(" "), children: [_jsxs(Div, { className: "relative overflow-hidden bg-zinc-100 dark:bg-slate-800 aspect-square", children: [product.mainImage ? (_jsx(MediaImage, { src: product.mainImage, alt: product.title, size: "card", className: "transition-transform duration-500 group-hover:scale-105" })) : (_jsx(Div, { className: "h-full w-full flex items-center justify-center bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-slate-800 dark:to-slate-700", children: _jsx(Span, { className: "text-4xl opacity-30", children: "\uD83D\uDECD\uFE0F" }) })), onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(product.id); }, label: isSelected ? "Deselect" : "Select", position: "top-2 left-2", className: selectionMode || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Div, { className: `absolute top-2 flex flex-col gap-1 ${onSelect ? "left-10" : "left-2"}`, children: !selectionMode && !isSelected && (_jsxs(_Fragment, { children: [discount && (_jsxs(Span, { className: "rounded-full bg-rose-500 px-2 py-0.5 text-[10px] font-bold text-white shadow-sm", children: ["-", discount, "%"] })), typeBadge && (_jsx(Span, { className: `rounded-full px-2 py-0.5 text-[10px] font-bold shadow-sm ${typeBadge.cls}`, children: typeBadge.label })), product.partOfBundleIds && product.partOfBundleIds.length > 0 && (_jsx(Span, { className: "rounded-full bg-teal-600 px-2 py-0.5 text-[10px] font-bold text-white shadow-sm", title: product.partOfBundleTitles && product.partOfBundleTitles.length > 0
51
51
  ? `In bundle: ${product.partOfBundleTitles[0]}`
52
- : "In a bundle", children: "Bundled" }))] })) }), onAddToWishlist && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => {
52
+ : "In a bundle", children: "Bundled" })), product.groupId && (_jsx(Span, { className: "rounded-full bg-indigo-600 px-2 py-0.5 text-[10px] font-bold text-white shadow-sm", title: product.groupTitle ? `Part of set: ${product.groupTitle}` : "Part of a set", children: product.isGroupParent ? "Set Parent" : "In Set" })), product.sublistingCategoryId && (_jsx(Span, { className: "rounded-full bg-sky-600 px-2 py-0.5 text-[10px] font-bold text-white shadow-sm", title: "Has variants or sub-listings", children: "Has Variants" }))] })) }), onAddToWishlist && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => {
53
53
  e.stopPropagation();
54
54
  e.preventDefault();
55
55
  onAddToWishlist(product.id);
@@ -59,7 +59,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
59
59
  isWishlisted
60
60
  ? "bg-rose-500 text-white hover:bg-rose-600"
61
61
  : "bg-white/90 dark:bg-slate-800/90 text-zinc-500 dark:text-zinc-400 hover:text-rose-500 hover:bg-white dark:hover:bg-slate-800",
62
- ].join(" "), children: _jsx("svg", { className: "h-4 w-4", fill: isWishlisted ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" }) }) }))] }), _jsxs(Div, { className: "flex flex-1 flex-col p-3 pt-2.5", children: [_jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-semibold text-zinc-900 dark:text-white leading-snug`, children: product.title }), (product.categoryName || product.brand) && (_jsxs(Row, { className: "mt-1 gap-1 flex-wrap", children: [product.categoryName && (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[90px]", children: product.categoryName })), product.brand && (_jsx(Span, { className: "rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[80px]", children: product.brand }))] })), (() => {
62
+ ].join(" "), children: _jsx("svg", { className: "h-4 w-4", fill: isWishlisted ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" }) }) }))] }), _jsxs(Div, { className: "flex flex-1 flex-col p-3 pt-2.5", children: [_jsx(Text, { className: `${THEME_CONSTANTS.utilities.textClamp2} text-sm font-semibold text-zinc-900 dark:text-white leading-snug`, children: product.title }), (product.categoryName || product.brand) && (_jsxs(Row, { className: "mt-1 gap-1 flex-wrap", children: [product.categoryName && (_jsxs(Span, { className: "inline-flex items-center gap-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[100px]", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 7a2 2 0 012-2h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7z" }) }), product.categoryName] })), product.brand && (_jsxs(Span, { className: "inline-flex items-center gap-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[90px]", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" }) }), product.brand] }))] })), (() => {
63
63
  const seller = safeDisplayName(product.storeName, "");
64
64
  return seller ? (_jsxs(Text, { className: "mt-0.5 text-[11px] text-zinc-400 dark:text-zinc-500 truncate", children: ["by ", seller] })) : null;
65
65
  })(), product.rating !== undefined && (_jsxs(Row, { className: "mt-1 gap-1 items-center", children: [_jsx(Span, { className: "text-[11px] text-amber-400", children: "\u2605" }), _jsxs(Span, { className: "text-[11px] text-zinc-500 dark:text-zinc-400", children: [product.rating.toFixed(1), product.reviewCount ? ` (${product.reviewCount})` : ""] })] })), _jsxs(Div, { className: "mt-auto pt-2", children: [_jsxs(Row, { className: "items-baseline gap-2", children: [_jsx(Span, { className: "text-base font-bold text-primary dark:text-primary-400", children: formatCurrency(product.price, getDefaultCurrency()) }), product.originalPrice && product.originalPrice > product.price && (_jsx(Span, { className: "text-xs text-zinc-400 line-through dark:text-zinc-500", children: formatCurrency(product.originalPrice, getDefaultCurrency()) }))] }), (() => {
@@ -81,7 +81,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
81
81
  e.stopPropagation();
82
82
  e.preventDefault();
83
83
  onAddToCart(product);
84
- }, className: "flex items-center justify-center gap-1 rounded-xl border-2 border-primary/30 py-2 text-xs font-semibold text-primary hover:bg-primary/5 hover:border-primary/50 active:scale-[0.97] transition-all duration-150 dark:text-primary-400 dark:border-primary-400/30 dark:hover:bg-primary/10", children: [_jsx("svg", { className: "h-3.5 w-3.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 3h2l.4 2M7 13h10l4-8H5.4m1.6 8L5 3H3m4 10v7a1 1 0 001 1h8a1 1 0 001-1v-7M9 21h6" }) }), "Cart"] }))] }))] })] })] }));
84
+ }, className: "flex items-center justify-center gap-1 rounded-xl border-2 border-primary/40 bg-primary/5 py-2 text-xs font-semibold text-primary hover:bg-primary/10 hover:border-primary/60 active:scale-[0.97] transition-all duration-150 dark:text-primary-400 dark:border-primary-400/50 dark:bg-primary/[0.08] dark:hover:bg-primary/[0.15] dark:hover:border-primary-400/70", children: [_jsx("svg", { className: "h-3.5 w-3.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 3h2l.4 2M7 13h10l4-8H5.4m1.6 8L5 3H3m4 10v7a1 1 0 001 1h8a1 1 0 001-1v-7M9 21h6" }) }), "Cart"] }))] }))] })] })] }));
85
85
  if (href && !selectionMode) {
86
86
  return (_jsx(Link, { href: href, className: "block h-full", children: cardBody }));
87
87
  }
@@ -79,6 +79,7 @@ export function ProductsIndexListing({ initialData }) {
79
79
  setSearchInput("");
80
80
  }, [table]);
81
81
  const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
82
+ const pendingFilterCount = FILTER_KEYS.filter((k) => !!pendingFilters[k]).length;
82
83
  const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
83
84
  table.get(TABLE_KEYS.SHOW_SOLD) === "true" ||
84
85
  table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
@@ -196,5 +197,5 @@ export function ProductsIndexListing({ initialData }) {
196
197
  ] }), 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: () => {
197
198
  setCompareIds([]);
198
199
  selection.clearSelection();
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})` : ""] }) })] })] }))] }));
200
+ }, 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: [pendingFilterCount > 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", pendingFilterCount > 0 ? ` (${pendingFilterCount})` : ""] }) })] })] }))] }));
200
201
  }
@@ -18,10 +18,14 @@ export const PRODUCT_FEATURE_CATEGORY_OPTIONS = [
18
18
  { value: "custom", label: "Custom" },
19
19
  ];
20
20
  export const PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS = [
21
- { value: "all", label: "All product types" },
21
+ { value: "all", label: "All listing types" },
22
22
  { value: "product", label: "Standard product" },
23
23
  { value: "auction", label: "Auction" },
24
24
  { value: "preorder", label: "Pre-order" },
25
+ { value: "prize-draw", label: "Prize draw" },
26
+ { value: "classified", label: "Classified" },
27
+ { value: "digital-code", label: "Digital code" },
28
+ { value: "live", label: "Live item" },
25
29
  ];
26
30
  export const PRODUCT_FEATURE_SCOPE_OPTIONS = [
27
31
  { value: "platform", label: "Platform (all stores)" },
@@ -315,6 +315,7 @@ export declare const productItemSchema: z.ZodObject<{
315
315
  preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
316
316
  prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
317
317
  categorySlug?: string | undefined;
318
+ features?: string[] | undefined;
318
319
  images?: string[] | undefined;
319
320
  description?: string | undefined;
320
321
  isPromoted?: boolean | undefined;
@@ -328,7 +329,6 @@ export declare const productItemSchema: z.ZodObject<{
328
329
  name: string;
329
330
  unit?: string | undefined;
330
331
  }[] | undefined;
331
- features?: string[] | undefined;
332
332
  shippingInfo?: string | undefined;
333
333
  returnPolicy?: string | undefined;
334
334
  insurance?: boolean | undefined;
@@ -444,6 +444,7 @@ export declare const productItemSchema: z.ZodObject<{
444
444
  preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
445
445
  prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
446
446
  categorySlug?: string | undefined;
447
+ features?: string[] | undefined;
447
448
  images?: string[] | undefined;
448
449
  description?: string | undefined;
449
450
  isPromoted?: boolean | undefined;
@@ -457,7 +458,6 @@ export declare const productItemSchema: z.ZodObject<{
457
458
  name: string;
458
459
  unit?: string | undefined;
459
460
  }[] | undefined;
460
- features?: string[] | undefined;
461
461
  shippingInfo?: string | undefined;
462
462
  returnPolicy?: string | undefined;
463
463
  insurance?: boolean | undefined;
@@ -20,7 +20,7 @@ export declare const MAX_STORE_CUSTOM_FEATURES = 20;
20
20
  export declare const MAX_FEATURES_PER_PRODUCT = 10;
21
21
  export type ProductFeatureScope = "platform" | "store";
22
22
  export type ProductFeatureCategory = "shipping" | "seller" | "condition" | "platform" | "auction" | "preorder" | "custom";
23
- export type ProductFeatureProductType = "product" | "auction" | "preorder" | "all";
23
+ export type ProductFeatureProductType = "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live" | "all";
24
24
  /**
25
25
  * Either an appkit icon-set name key (e.g. "truck") or a raw SVG path-d string.
26
26
  * Path strings must start with "M " — see isFeatureIconPath().
@@ -6,7 +6,7 @@
6
6
  * of hand-rolling parallel schemas.
7
7
  */
8
8
  import { z } from "zod";
9
- export declare const PRODUCT_FEATURE_PRODUCT_TYPE_ENUM: z.ZodEnum<["product", "auction", "preorder", "all"]>;
9
+ export declare const PRODUCT_FEATURE_PRODUCT_TYPE_ENUM: z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>;
10
10
  export declare const PRODUCT_FEATURE_CATEGORY_ENUM: z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>;
11
11
  export declare const PRODUCT_FEATURE_SCOPE_ENUM: z.ZodEnum<["platform", "store"]>;
12
12
  /** Shape for POST /api/admin/features — admin creates either scope. */
@@ -17,7 +17,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
17
17
  iconColor: z.ZodOptional<z.ZodString>;
18
18
  category: z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>;
19
19
  scope: z.ZodEnum<["platform", "store"]>;
20
- productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "all"]>, "many">;
20
+ productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>, "many">;
21
21
  storeId: z.ZodOptional<z.ZodString>;
22
22
  isActive: z.ZodBoolean;
23
23
  displayOrder: z.ZodNumber;
@@ -28,7 +28,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
28
28
  isActive: boolean;
29
29
  category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
30
30
  displayOrder: number;
31
- productTypes: ("all" | "product" | "auction" | "preorder")[];
31
+ productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
32
32
  storeId?: string | undefined;
33
33
  description?: string | undefined;
34
34
  iconColor?: string | undefined;
@@ -39,7 +39,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
39
39
  isActive: boolean;
40
40
  category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
41
41
  displayOrder: number;
42
- productTypes: ("all" | "product" | "auction" | "preorder")[];
42
+ productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
43
43
  storeId?: string | undefined;
44
44
  description?: string | undefined;
45
45
  iconColor?: string | undefined;
@@ -51,7 +51,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
51
51
  icon: z.ZodString;
52
52
  iconColor: z.ZodOptional<z.ZodString>;
53
53
  category: z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>;
54
- productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "all"]>, "many">;
54
+ productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>, "many">;
55
55
  isActive: z.ZodBoolean;
56
56
  displayOrder: z.ZodNumber;
57
57
  }, "strip", z.ZodTypeAny, {
@@ -60,7 +60,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
60
60
  isActive: boolean;
61
61
  category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
62
62
  displayOrder: number;
63
- productTypes: ("all" | "product" | "auction" | "preorder")[];
63
+ productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
64
64
  description?: string | undefined;
65
65
  iconColor?: string | undefined;
66
66
  }, {
@@ -69,7 +69,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
69
69
  isActive: boolean;
70
70
  category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
71
71
  displayOrder: number;
72
- productTypes: ("all" | "product" | "auction" | "preorder")[];
72
+ productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
73
73
  description?: string | undefined;
74
74
  iconColor?: string | undefined;
75
75
  }>;
@@ -80,7 +80,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
80
80
  icon: z.ZodOptional<z.ZodString>;
81
81
  iconColor: z.ZodOptional<z.ZodString>;
82
82
  category: z.ZodOptional<z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>>;
83
- productTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "all"]>, "many">>;
83
+ productTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>, "many">>;
84
84
  isActive: z.ZodOptional<z.ZodBoolean>;
85
85
  displayOrder: z.ZodOptional<z.ZodNumber>;
86
86
  }, "strip", z.ZodTypeAny, {
@@ -91,7 +91,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
91
91
  description?: string | undefined;
92
92
  iconColor?: string | undefined;
93
93
  displayOrder?: number | undefined;
94
- productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
94
+ productTypes?: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[] | undefined;
95
95
  }, {
96
96
  label?: string | undefined;
97
97
  icon?: string | undefined;
@@ -100,7 +100,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
100
100
  description?: string | undefined;
101
101
  iconColor?: string | undefined;
102
102
  displayOrder?: number | undefined;
103
- productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
103
+ productTypes?: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[] | undefined;
104
104
  }>;
105
105
  export type ProductFeatureAdminCreatePayload = z.infer<typeof productFeatureAdminCreateSchema>;
106
106
  export type ProductFeatureStoreCreatePayload = z.infer<typeof productFeatureStoreCreateSchema>;
@@ -10,6 +10,10 @@ export const PRODUCT_FEATURE_PRODUCT_TYPE_ENUM = z.enum([
10
10
  "product",
11
11
  "auction",
12
12
  "preorder",
13
+ "prize-draw",
14
+ "classified",
15
+ "digital-code",
16
+ "live",
13
17
  "all",
14
18
  ]);
15
19
  export const PRODUCT_FEATURE_CATEGORY_ENUM = z.enum([
@@ -61,7 +61,7 @@ export function SellerCouponEditorView({ couponId, initial, onSave, onCancel, })
61
61
  }
62
62
  };
63
63
  const isEdit = Boolean(couponId);
64
- return (_jsx("form", { onSubmit: handleSubmit, noValidate: true, children: _jsxs(Stack, { gap: "none", className: "max-w-lg mx-auto", children: [_jsx(Div, { className: "border-b border-[var(--appkit-color-border,#e5e7eb)] dark:border-[var(--appkit-color-border-dark,#374151)] px-6 py-5", children: _jsxs(Row, { className: "items-center justify-between gap-3", children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-[var(--appkit-color-text-primary)]", children: isEdit ? "Edit Coupon" : "Create Coupon" }), isEdit && (_jsx(Badge, { variant: draft.isActive ? "success" : "default", children: draft.isActive ? "Active" : "Inactive" }))] }) }), _jsxs(Stack, { gap: "5", className: "px-6 py-6", children: [error && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-red-50 dark:bg-red-950/40 dark:border-red-900/60 px-4 py-3 text-sm text-red-700 dark:text-red-200", children: error })), _jsx(Input, { label: "Coupon Code", value: draft.code, onChange: (e) => set("code", e.target.value.toUpperCase().replace(/\s+/g, "")), placeholder: "e.g. WELCOME10", required: true, disabled: isEdit, helperText: isEdit ? "Code cannot be changed after creation" : "Customers enter this at checkout" }), _jsx(Select, { label: "Discount Type", value: draft.type, options: TYPE_OPTIONS, onChange: (e) => set("type", e.target.value) }), draft.type !== "free_shipping" && (_jsx(Input, { label: draft.type === "percentage" ? "Discount Percentage (%)" : "Discount Amount (₹)", type: "number", min: 1, max: draft.type === "percentage" ? 100 : undefined, value: draft.value, onChange: (e) => set("value", e.target.value), placeholder: draft.type === "percentage" ? "e.g. 10" : "e.g. 50", required: true, helperText: draft.type === "percentage"
64
+ return (_jsx("form", { onSubmit: handleSubmit, noValidate: true, children: _jsxs(Stack, { gap: "none", className: "max-w-lg mx-auto rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] shadow-sm overflow-hidden", children: [_jsx("div", { className: "h-[3px] w-full", style: { background: "linear-gradient(to right,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 55%,var(--appkit-color-secondary-400,#84e122) 100%)" }, "aria-hidden": "true" }), _jsx(Div, { className: "border-b border-[var(--appkit-color-border)] px-6 py-5", children: _jsxs(Row, { className: "items-center justify-between gap-3", children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-[var(--appkit-color-text)]", children: isEdit ? "Edit Coupon" : "Create Coupon" }), isEdit && (_jsx(Badge, { variant: draft.isActive ? "success" : "default", children: draft.isActive ? "Active" : "Inactive" }))] }) }), _jsxs(Stack, { gap: "5", className: "px-6 py-6", children: [error && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-red-50 dark:bg-red-950/40 dark:border-red-900/60 px-4 py-3 text-sm text-red-700 dark:text-red-200", children: error })), _jsx(Input, { label: "Coupon Code", value: draft.code, onChange: (e) => set("code", e.target.value.toUpperCase().replace(/\s+/g, "")), placeholder: "e.g. WELCOME10", required: true, disabled: isEdit, helperText: isEdit ? "Code cannot be changed after creation" : "Customers enter this at checkout" }), _jsx(Select, { label: "Discount Type", value: draft.type, options: TYPE_OPTIONS, onChange: (e) => set("type", e.target.value) }), draft.type !== "free_shipping" && (_jsx(Input, { label: draft.type === "percentage" ? "Discount Percentage (%)" : "Discount Amount (₹)", type: "number", min: 1, max: draft.type === "percentage" ? 100 : undefined, value: draft.value, onChange: (e) => set("value", e.target.value), placeholder: draft.type === "percentage" ? "e.g. 10" : "e.g. 50", required: true, helperText: draft.type === "percentage"
65
65
  ? "Enter a value between 1 and 100"
66
- : "Fixed rupee discount applied to the order" })), draft.type === "percentage" && (_jsx(Input, { label: "Max Discount Cap (\u20B9, optional)", type: "number", min: 0, value: draft.maxDiscount, onChange: (e) => set("maxDiscount", e.target.value), placeholder: "Leave blank for no cap", helperText: "Maximum rupee discount regardless of percentage" })), _jsx(Input, { label: "Minimum Order Amount (\u20B9, optional)", type: "number", min: 0, value: draft.minPurchase, onChange: (e) => set("minPurchase", e.target.value), placeholder: "Leave blank for no minimum" }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Usage Limits" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Total Uses", type: "number", min: 0, value: draft.totalLimit, onChange: (e) => set("totalLimit", e.target.value), placeholder: "0 = unlimited" }), _jsx(Input, { label: "Per Customer", type: "number", min: 0, value: draft.perUserLimit, onChange: (e) => set("perUserLimit", e.target.value), placeholder: "0 = unlimited" })] })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Validity Period" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Start Date", type: "date", value: draft.startDate, onChange: (e) => set("startDate", e.target.value), required: true }), _jsx(Input, { label: "End Date", type: "date", value: draft.endDate, onChange: (e) => set("endDate", e.target.value), required: true })] })] }), _jsx(Div, { className: "flex items-center gap-3 rounded-lg border border-[var(--appkit-color-border)] dark:border-[var(--appkit-color-border-dark)] px-4 py-3", children: _jsxs("label", { className: "flex items-center gap-3 cursor-pointer w-full", children: [_jsx("input", { type: "checkbox", checked: draft.isActive, onChange: (e) => set("isActive", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-primary)]", children: "Active" }), _jsx(Text, { size: "xs", className: "text-[var(--appkit-color-text-secondary)]", children: "Customers can apply this coupon at checkout" })] })] }) })] }), _jsx(Div, { className: "border-t border-[var(--appkit-color-border)] dark:border-[var(--appkit-color-border-dark)] px-6 py-4", children: _jsxs(Row, { className: "items-center justify-end gap-3", children: [onCancel && (_jsx(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: saving, children: "Cancel" })), _jsx(Button, { type: "submit", isLoading: saving, disabled: saving, children: isEdit ? "Save Changes" : "Create Coupon" })] }) })] }) }));
66
+ : "Fixed rupee discount applied to the order" })), draft.type === "percentage" && (_jsx(Input, { label: "Max Discount Cap (\u20B9, optional)", type: "number", min: 0, value: draft.maxDiscount, onChange: (e) => set("maxDiscount", e.target.value), placeholder: "Leave blank for no cap", helperText: "Maximum rupee discount regardless of percentage" })), _jsx(Input, { label: "Minimum Order Amount (\u20B9, optional)", type: "number", min: 0, value: draft.minPurchase, onChange: (e) => set("minPurchase", e.target.value), placeholder: "Leave blank for no minimum" }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Usage Limits" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Total Uses", type: "number", min: 0, value: draft.totalLimit, onChange: (e) => set("totalLimit", e.target.value), placeholder: "0 = unlimited" }), _jsx(Input, { label: "Per Customer", type: "number", min: 0, value: draft.perUserLimit, onChange: (e) => set("perUserLimit", e.target.value), placeholder: "0 = unlimited" })] })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Validity Period" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Start Date", type: "date", value: draft.startDate, onChange: (e) => set("startDate", e.target.value), required: true }), _jsx(Input, { label: "End Date", type: "date", value: draft.endDate, onChange: (e) => set("endDate", e.target.value), required: true })] })] }), _jsx(Div, { className: "flex items-center gap-3 rounded-lg border border-[var(--appkit-color-border)] dark:border-[var(--appkit-color-border-dark)] px-4 py-3", children: _jsxs("label", { className: "flex items-center gap-3 cursor-pointer w-full", children: [_jsx("input", { type: "checkbox", checked: draft.isActive, onChange: (e) => set("isActive", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-primary)]", children: "Active" }), _jsx(Text, { size: "xs", className: "text-[var(--appkit-color-text-secondary)]", children: "Customers can apply this coupon at checkout" })] })] }) })] }), _jsx(Div, { className: "border-t border-[var(--appkit-color-border)] px-6 py-4", children: _jsxs(Row, { className: "items-center justify-end gap-3", children: [onCancel && (_jsx(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: saving, children: "Cancel" })), _jsx(Button, { type: "submit", isLoading: saving, disabled: saving, children: isEdit ? "Save Changes" : "Create Coupon" })] }) })] }) }));
67
67
  }
@@ -1,8 +1,14 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Div, Heading, Span, Text } from "../../../../ui";
3
- function SellerAnalyticsStatCard({ label, value, icon, colorClassName, }) {
4
- return (_jsx(Div, { className: "bg-white dark:bg-neutral-900 rounded-xl border border-neutral-200 dark:border-neutral-800 p-4 sm:p-5", children: _jsxs(Div, { className: "flex items-start justify-between gap-3", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-xs sm:text-sm text-neutral-600 dark:text-neutral-400 font-medium uppercase tracking-wide", children: label }), _jsx(Heading, { level: 3, className: `mt-1 text-2xl font-bold ${colorClassName}`, children: value })] }), _jsx(Span, { className: "text-2xl sm:text-3xl", "aria-hidden": true, children: icon })] }) }));
3
+ import { TrendingUp, ShoppingBag, Package, CheckCircle } from "lucide-react";
4
+ import { Div } from "../../../../ui";
5
+ const GREEN_GRAD = "linear-gradient(135deg,var(--appkit-color-cobalt,#3570fc) 0%,var(--appkit-color-secondary-400,#84e122) 100%)";
6
+ const BRAND_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 55%,var(--appkit-color-secondary-400,#84e122) 100%)";
7
+ const AMBER_GRAD = "linear-gradient(135deg,var(--appkit-color-amber-500,#f59e0b) 0%,var(--appkit-color-amber-600,#d97706) 100%)";
8
+ const BLUE_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 100%)";
9
+ function StatCard({ label, value, gradient, Icon }) {
10
+ return (_jsxs(Div, { className: "relative rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] overflow-hidden shadow-sm hover:shadow-md transition-shadow", children: [_jsx("div", { className: "absolute top-0 left-0 right-0 h-[3px]", style: { background: gradient }, "aria-hidden": "true" }), _jsxs(Div, { className: "px-5 pb-5 pt-6 flex items-start justify-between gap-3", children: [_jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[11px] font-semibold uppercase tracking-widest text-[var(--appkit-color-text-muted)]", children: label }), _jsx("div", { className: "mt-2 text-2xl font-bold text-[var(--appkit-color-text)] tabular-nums leading-none", children: value })] }), _jsx("div", { className: "flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center", style: { background: gradient }, children: _jsx(Icon, { className: "w-5 h-5 text-white" }) })] })] }));
5
11
  }
6
12
  export function SellerAnalyticsStats({ summary, labels = {}, formatRevenue = (amount) => String(amount), className = "", }) {
7
- return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(SellerAnalyticsStatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), icon: "\uD83D\uDCB0", colorClassName: "text-emerald-600 dark:text-emerald-400" }), _jsx(SellerAnalyticsStatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), icon: "\uD83D\uDCE6", colorClassName: "text-blue-600 dark:text-blue-400" }), _jsx(SellerAnalyticsStatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), icon: "\uD83D\uDECD\uFE0F", colorClassName: "text-violet-600 dark:text-violet-400" }), _jsx(SellerAnalyticsStatCard, { label: labels.publishedProducts ?? "Published Products", value: String(summary.publishedProducts), icon: "\u2705", colorClassName: "text-amber-600 dark:text-amber-400" })] }));
13
+ return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(StatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), gradient: GREEN_GRAD, Icon: TrendingUp }), _jsx(StatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), gradient: BRAND_GRAD, Icon: ShoppingBag }), _jsx(StatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), gradient: AMBER_GRAD, Icon: Package }), _jsx(StatCard, { label: labels.publishedProducts ?? "Published", value: String(summary.publishedProducts), gradient: BLUE_GRAD, Icon: CheckCircle })] }));
8
14
  }
@@ -101,5 +101,5 @@ export function FormShell({ isOpen, onClose, title, breadcrumb, isDirty = false,
101
101
  };
102
102
  if (!isOpen)
103
103
  return null;
104
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/50 backdrop-blur-[2px]", style: { zIndex: "calc(var(--appkit-z-modal) - 1)" }, "aria-hidden": "true", onClick: attemptClose }), _jsxs("div", { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: "fixed inset-0 flex flex-col bg-[var(--appkit-color-surface)] shadow-2xl", style: { zIndex: "var(--appkit-z-modal)" }, children: [_jsxs("div", { className: "flex-shrink-0 sticky top-0 z-10 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-4 py-3 flex items-center gap-3", children: [previewMode ? (_jsxs("button", { type: "button", onClick: () => setPreviewMode(false), "aria-label": "Back to edit", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0 flex items-center gap-1.5 text-sm", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Back to Edit" })] })) : (_jsx("button", { type: "button", onClick: attemptClose, "aria-label": "Close", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })), _jsxs("div", { className: "flex-1 min-w-0", children: [breadcrumb && (_jsx("p", { className: "text-xs text-[var(--appkit-color-text-muted)] truncate mb-0.5", children: breadcrumb })), _jsx("p", { className: "text-sm font-semibold text-[var(--appkit-color-text)] truncate", children: previewMode ? `Preview — ${title}` : title })] }), _jsx("div", { className: "flex items-center gap-2 flex-shrink-0", children: previewMode ? null : (_jsxs(_Fragment, { children: [previewSlot && (_jsxs("button", { type: "button", onClick: () => setPreviewMode(true), className: "flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors border border-[var(--appkit-color-border)]", children: [_jsx(Eye, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Preview" })] })), onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsx(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: publishLabel }))] })) })] }), _jsxs("div", { className: "flex flex-1 overflow-hidden", children: [sections && sections.length > 0 && !previewMode && (_jsx("nav", { "aria-label": "Form sections", className: "hidden lg:flex flex-col flex-shrink-0 w-48 border-r border-[var(--appkit-color-border)] py-4 px-3 gap-1 overflow-y-auto", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "text-left text-sm px-3 py-2 rounded-lg text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors", children: sec.label }, sec.id))) })), sections && sections.length > 0 && !previewMode && (_jsx("div", { className: "lg:hidden fixed top-[var(--form-shell-topbar-h,57px)] left-0 right-0 z-10 flex overflow-x-auto gap-1 px-4 py-2 bg-[var(--appkit-color-surface)] border-b border-[var(--appkit-color-border)]", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "flex-shrink-0 text-xs px-3 py-1.5 rounded-full border border-[var(--appkit-color-border)] text-[var(--appkit-color-text-muted)] hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] transition-colors whitespace-nowrap", children: sec.label }, sec.id))) })), _jsx("div", { ref: bodyRef, className: classNames("flex-1 overflow-y-auto", sections && sections.length > 0 && !previewMode ? "pt-0 lg:pt-0" : ""), children: previewMode && previewSlot ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sticky top-0 z-10 flex items-center gap-2 bg-[var(--appkit-color-warning-surface)] border-b border-[var(--appkit-color-warning)] px-4 py-2 text-sm text-[var(--appkit-color-warning-text,var(--appkit-color-warning))]", children: [_jsx(Eye, { className: "w-4 h-4 flex-shrink-0" }), _jsx("span", { children: "Preview \u2014 not visible to buyers until published" })] }), _jsx("div", { className: "py-4", children: previewSlot() })] })) : (_jsx("div", { className: "max-w-3xl mx-auto px-4 py-6 sm:px-6", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs("div", { className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-4 py-3 flex items-center justify-between", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), _jsxs("div", { className: "flex items-center gap-2", children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/60", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, onClick: () => setShowUnsaved(false) }), _jsxs("div", { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)] rounded-xl shadow-2xl p-6", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, children: [_jsxs("div", { className: "flex gap-3 mb-4", children: [_jsx("span", { className: "flex-shrink-0 w-10 h-10 rounded-full bg-[var(--appkit-color-warning-surface)] flex items-center justify-center", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold text-[var(--appkit-color-text)]", children: "Unsaved changes" }), _jsx("p", { className: "text-sm text-[var(--appkit-color-text-muted)] mt-1", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs("div", { className: "flex gap-2 justify-end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
104
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/50 backdrop-blur-[2px]", style: { zIndex: "calc(var(--appkit-z-modal) - 1)" }, "aria-hidden": "true", onClick: attemptClose }), _jsxs("div", { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: "fixed top-0 bottom-0 left-0 right-0 lg:left-[10%] lg:right-[10%] flex flex-col bg-[var(--appkit-color-surface)] shadow-2xl", style: { zIndex: "var(--appkit-z-modal)" }, children: [_jsxs("div", { className: "flex-shrink-0 sticky top-0 z-10 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-4 py-3 flex items-center gap-3", children: [previewMode ? (_jsxs("button", { type: "button", onClick: () => setPreviewMode(false), "aria-label": "Back to edit", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0 flex items-center gap-1.5 text-sm", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Back to Edit" })] })) : (_jsx("button", { type: "button", onClick: attemptClose, "aria-label": "Close", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })), _jsxs("div", { className: "flex-1 min-w-0", children: [breadcrumb && (_jsx("p", { className: "text-xs text-[var(--appkit-color-text-muted)] truncate mb-0.5", children: breadcrumb })), _jsx("p", { className: "text-sm font-semibold text-[var(--appkit-color-text)] truncate", children: previewMode ? `Preview — ${title}` : title })] }), _jsx("div", { className: "flex items-center gap-2 flex-shrink-0", children: previewMode ? null : (_jsxs(_Fragment, { children: [previewSlot && (_jsxs("button", { type: "button", onClick: () => setPreviewMode(true), className: "flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors border border-[var(--appkit-color-border)]", children: [_jsx(Eye, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Preview" })] })), onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsx(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: publishLabel }))] })) })] }), _jsxs("div", { className: "flex flex-1 overflow-hidden", children: [sections && sections.length > 0 && !previewMode && (_jsx("nav", { "aria-label": "Form sections", className: "hidden lg:flex flex-col flex-shrink-0 w-48 border-r border-[var(--appkit-color-border)] py-4 px-3 gap-1 overflow-y-auto", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "text-left text-sm px-3 py-2 rounded-lg text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors", children: sec.label }, sec.id))) })), sections && sections.length > 0 && !previewMode && (_jsx("div", { className: "lg:hidden fixed top-[var(--form-shell-topbar-h,57px)] left-0 right-0 z-10 flex overflow-x-auto gap-1 px-4 py-2 bg-[var(--appkit-color-surface)] border-b border-[var(--appkit-color-border)]", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "flex-shrink-0 text-xs px-3 py-1.5 rounded-full border border-[var(--appkit-color-border)] text-[var(--appkit-color-text-muted)] hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] transition-colors whitespace-nowrap", children: sec.label }, sec.id))) })), _jsx("div", { ref: bodyRef, className: classNames("flex-1 overflow-y-auto", sections && sections.length > 0 && !previewMode ? "pt-0 lg:pt-0" : ""), children: previewMode && previewSlot ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sticky top-0 z-10 flex items-center gap-2 bg-[var(--appkit-color-warning-surface)] border-b border-[var(--appkit-color-warning)] px-4 py-2 text-sm text-[var(--appkit-color-warning-text,var(--appkit-color-warning))]", children: [_jsx(Eye, { className: "w-4 h-4 flex-shrink-0" }), _jsx("span", { children: "Preview \u2014 not visible to buyers until published" })] }), _jsx("div", { className: "py-4", children: previewSlot() })] })) : (_jsx("div", { className: "max-w-3xl mx-auto px-4 py-6 sm:px-6", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs("div", { className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-4 py-3 flex items-center justify-between", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), _jsxs("div", { className: "flex items-center gap-2", children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/60", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, onClick: () => setShowUnsaved(false) }), _jsxs("div", { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)] rounded-xl shadow-2xl p-6", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, children: [_jsxs("div", { className: "flex gap-3 mb-4", children: [_jsx("span", { className: "flex-shrink-0 w-10 h-10 rounded-full bg-[var(--appkit-color-warning-surface)] flex items-center justify-center", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold text-[var(--appkit-color-text)]", children: "Unsaved changes" }), _jsx("p", { className: "text-sm text-[var(--appkit-color-text-muted)] mt-1", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs("div", { className: "flex gap-2 justify-end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
105
105
  }
@@ -1,5 +1,8 @@
1
1
  export interface StoreBundlesPageViewProps {
2
2
  storeSlug: string;
3
+ onBuyNow?: (input: {
4
+ bundleSlug: string;
5
+ }) => Promise<unknown>;
3
6
  }
4
7
  /**
5
8
  * Public store → Bundles tab.
@@ -9,4 +12,4 @@ export interface StoreBundlesPageViewProps {
9
12
  * the seller's active bundle categories and hands them to
10
13
  * `CategoryBundlesListing`. Mirrors the StorePrizeDrawsPageView pattern.
11
14
  */
12
- export declare function StoreBundlesPageView({ storeSlug, }: StoreBundlesPageViewProps): Promise<import("react/jsx-runtime").JSX.Element | null>;
15
+ export declare function StoreBundlesPageView({ storeSlug, onBuyNow, }: StoreBundlesPageViewProps): Promise<import("react/jsx-runtime").JSX.Element | null>;
@@ -10,7 +10,7 @@ import { CategoryBundlesListing } from "../../categories/components/CategoryBund
10
10
  * the seller's active bundle categories and hands them to
11
11
  * `CategoryBundlesListing`. Mirrors the StorePrizeDrawsPageView pattern.
12
12
  */
13
- export async function StoreBundlesPageView({ storeSlug, }) {
13
+ export async function StoreBundlesPageView({ storeSlug, onBuyNow, }) {
14
14
  const store = await getStoreBySlug(storeSlug);
15
15
  const storeId = store?.id;
16
16
  if (!storeId) {
@@ -20,5 +20,5 @@ export async function StoreBundlesPageView({ storeSlug, }) {
20
20
  .listByType("bundle", { activeOnly: true, limit: 50 })
21
21
  .then((rows) => rows.filter((c) => c.createdByStoreId === storeId))
22
22
  .catch(() => []);
23
- return _jsx(CategoryBundlesListing, { initialBundles: bundles });
23
+ return _jsx(CategoryBundlesListing, { initialBundles: bundles, onBuyNow: onBuyNow });
24
24
  }
@@ -80,6 +80,7 @@ export function StoresIndexListing({ initialData }) {
80
80
  setSearchInput("");
81
81
  }, [table]);
82
82
  const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
83
+ const pendingFilterCount = FILTER_KEYS.filter((k) => !!pendingFilters[k]).length;
83
84
  const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
84
85
  table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
85
86
  activeFilterCount > 0;
@@ -132,5 +133,5 @@ export function StoresIndexListing({ initialData }) {
132
133
  }) })) : (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: stores.map((store) => {
133
134
  const storeKey = store.storeSlug ?? store.id;
134
135
  return (_jsx(InteractiveStoreCard, { store: store, href: String(ROUTES.PUBLIC.STORE_DETAIL(storeKey)), selectable: selection.isSelecting, isSelected: selection.isSelected(store.id ?? store.storeSlug), onSelect: (id, sel) => { void sel; selection.toggle(id); } }, storeKey));
135
- }) })) }), 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(StoreFilters, { table: pendingTable }) }), _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})` : ""] }) })] })] }))] }));
136
+ }) })) }), 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: [pendingFilterCount > 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(StoreFilters, { table: pendingTable }) }), _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", pendingFilterCount > 0 ? ` (${pendingFilterCount})` : ""] }) })] })] }))] }));
136
137
  }
@@ -10,8 +10,8 @@ export interface WishlistCapEventDetail {
10
10
  *
11
11
  * Server-authoritative count for the badge. For authenticated users this
12
12
  * mirrors `/api/wishlist` via react-query (same `["wishlist", uid]` key as
13
- * `useWishlist`), so mutations on the wishlist page propagate to the badge
14
- * via standard query invalidation. For guests, falls back to the localStorage
13
+ * `useWishlist`), storing a full WishlistResponse so both hooks share the
14
+ * cache without type collisions. For guests, falls back to the localStorage
15
15
  * guest store.
16
16
  *
17
17
  * On login the hook pushes any guest items up to the server once, then clears
@@ -15,17 +15,13 @@ function dispatchCapEvent(detail) {
15
15
  return;
16
16
  window.dispatchEvent(new CustomEvent(WISHLIST_CAP_EVENT, { detail }));
17
17
  }
18
- async function fetchServerCount(userId) {
19
- const data = await apiClient.get(WISHLIST_ENDPOINTS.BY_USER(userId));
20
- return data?.total ?? data?.items?.length ?? 0;
21
- }
22
18
  /**
23
19
  * useWishlistCount
24
20
  *
25
21
  * Server-authoritative count for the badge. For authenticated users this
26
22
  * mirrors `/api/wishlist` via react-query (same `["wishlist", uid]` key as
27
- * `useWishlist`), so mutations on the wishlist page propagate to the badge
28
- * via standard query invalidation. For guests, falls back to the localStorage
23
+ * `useWishlist`), storing a full WishlistResponse so both hooks share the
24
+ * cache without type collisions. For guests, falls back to the localStorage
29
25
  * guest store.
30
26
  *
31
27
  * On login the hook pushes any guest items up to the server once, then clears
@@ -36,12 +32,13 @@ export function useWishlistCount(userId) {
36
32
  const queryClient = useQueryClient();
37
33
  const mergedRef = useRef(null);
38
34
  const pathname = usePathname();
39
- const { data: serverTotal } = useQuery({
35
+ const { data: wishlistData } = useQuery({
40
36
  queryKey: ["wishlist", userId],
41
- queryFn: () => fetchServerCount(userId),
37
+ queryFn: () => apiClient.get(WISHLIST_ENDPOINTS.BY_USER(userId)),
42
38
  enabled: !!userId,
43
39
  staleTime: 30000,
44
40
  });
41
+ const serverTotal = wishlistData?.total ?? wishlistData?.items?.length ?? 0;
45
42
  // Merge on login: push guest items → server once, then clear local store.
46
43
  useEffect(() => {
47
44
  if (!userId) {
@@ -24,12 +24,14 @@ export function getAdminAppLite() {
24
24
  return existing;
25
25
  }
26
26
  const keyPath = nodePath().join(nodeCwd(), "firebase-admin-key.json");
27
+ const storageBucket = process.env.FIREBASE_ADMIN_STORAGE_BUCKET?.trim() ??
28
+ process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET?.trim();
27
29
  let app;
28
30
  if (nodeFs().existsSync(keyPath)) {
29
31
  const sa = JSON.parse(nodeFs().readFileSync(keyPath, "utf8"));
30
32
  const dbUrl = process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL ??
31
33
  `https://${sa.project_id}-default-rtdb.firebaseio.com`;
32
- app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl });
34
+ app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl, ...(storageBucket && { storageBucket }) });
33
35
  }
34
36
  else if (process.env.FIREBASE_ADMIN_PROJECT_ID &&
35
37
  process.env.FIREBASE_ADMIN_CLIENT_EMAIL &&
@@ -45,6 +47,7 @@ export function getAdminAppLite() {
45
47
  privateKey: parsePrivateKey(process.env.FIREBASE_ADMIN_PRIVATE_KEY),
46
48
  }),
47
49
  databaseURL: dbUrl,
50
+ ...(storageBucket && { storageBucket }),
48
51
  });
49
52
  }
50
53
  else if (
@@ -66,7 +69,10 @@ export function getAdminAppLite() {
66
69
  process.env.FIREBASE_ADMIN_DATABASE_URL ??
67
70
  process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL ??
68
71
  (projectId ? `https://${projectId}-default-rtdb.firebaseio.com` : undefined);
69
- app = initializeApp(dbUrl ? { databaseURL: dbUrl } : undefined);
72
+ app = initializeApp({
73
+ ...(dbUrl && { databaseURL: dbUrl }),
74
+ ...(storageBucket && { storageBucket }),
75
+ });
70
76
  }
71
77
  else {
72
78
  throw new Error("@mohasinac/db-firebase: Firebase Admin credentials not found.");
@@ -67,13 +67,15 @@ export function getAdminApp() {
67
67
  return existing;
68
68
  }
69
69
  const keyPath = nodePath().join(nodeCwd(), "firebase-admin-key.json");
70
+ const storageBucket = process.env.FIREBASE_ADMIN_STORAGE_BUCKET?.trim() ??
71
+ process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET?.trim();
70
72
  let app;
71
73
  try {
72
74
  if (nodeFs().existsSync(keyPath)) {
73
75
  const sa = JSON.parse(nodeFs().readFileSync(keyPath, "utf8"));
74
76
  const dbUrl = process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL ??
75
77
  `https://${sa.project_id}-default-rtdb.firebaseio.com`;
76
- app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl });
78
+ app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl, ...(storageBucket && { storageBucket }) });
77
79
  }
78
80
  else if (process.env.FIREBASE_ADMIN_PROJECT_ID &&
79
81
  process.env.FIREBASE_ADMIN_CLIENT_EMAIL &&
@@ -89,6 +91,7 @@ export function getAdminApp() {
89
91
  privateKey: parsePrivateKey(process.env.FIREBASE_ADMIN_PRIVATE_KEY),
90
92
  }),
91
93
  databaseURL: dbUrl,
94
+ ...(storageBucket && { storageBucket }),
92
95
  });
93
96
  }
94
97
  else if (
@@ -112,7 +115,10 @@ export function getAdminApp() {
112
115
  (projectId
113
116
  ? `https://${projectId}-default-rtdb.firebaseio.com`
114
117
  : undefined);
115
- app = initializeApp(dbUrl ? { databaseURL: dbUrl } : undefined);
118
+ app = initializeApp({
119
+ ...(dbUrl && { databaseURL: dbUrl }),
120
+ ...(storageBucket && { storageBucket }),
121
+ });
116
122
  }
117
123
  else {
118
124
  throw new Error("@mohasinac/db-firebase: Firebase Admin credentials not found.\n" +
@@ -197,14 +197,14 @@ export const addressesSeedData = [
197
197
  updatedAt: daysAgo(739),
198
198
  },
199
199
  // ============================================
200
- // Admin User's Address
200
+ // Admin User's Addresses (user-admin-letitrip)
201
201
  // ============================================
202
202
  {
203
203
  id: "addr-admin-primary-1707400017",
204
- userId: "user-admin-user-admin",
205
- label: "Primary",
206
- fullName: "Admin User",
207
- phone: `${_phonePrefix}9876543210`,
204
+ userId: "user-admin-letitrip",
205
+ label: "Office (LetItRip HQ)",
206
+ fullName: "LetItRip Admin",
207
+ phone: `${_phonePrefix}9876500000`,
208
208
  addressLine1: "LetItRip HQ, 10th Floor",
209
209
  addressLine2: "BKC, G Block",
210
210
  city: "Mumbai",
@@ -212,7 +212,24 @@ export const addressesSeedData = [
212
212
  postalCode: "400051",
213
213
  country: _locale.countryName,
214
214
  isDefault: true,
215
- createdAt: daysAgo(799),
216
- updatedAt: daysAgo(799),
215
+ createdAt: daysAgo(399),
216
+ updatedAt: daysAgo(30),
217
+ },
218
+ {
219
+ id: "addr-admin-home-1707400018",
220
+ userId: "user-admin-letitrip",
221
+ label: "Home",
222
+ fullName: "LetItRip Admin",
223
+ phone: `${_phonePrefix}9876500000`,
224
+ addressLine1: "A-1204, Kalpataru Horizon",
225
+ addressLine2: "S.K. Ahire Marg, Worli",
226
+ landmark: "Near Worli Sea Face",
227
+ city: "Mumbai",
228
+ state: "Maharashtra",
229
+ postalCode: "400018",
230
+ country: _locale.countryName,
231
+ isDefault: false,
232
+ createdAt: daysAgo(300),
233
+ updatedAt: daysAgo(30),
217
234
  },
218
235
  ];
@@ -1,19 +1,19 @@
1
1
  /**
2
- * Carts Seed Data — LetItRip Collectibles
2
+ * Carts Seed Data â€" LetItRip Collectibles
3
3
  *
4
4
  * Covers all cart states for testing Add-to-Cart / Update / Remove / Checkout flows:
5
- * — Multi-item cart (cross-store, mixed categories) — Rahul Sharma
6
- * — Single-item cart — Priya Patel
7
- * — Cart with auction item — Arjun Singh
8
- * — Cart with quantity > 1 — Meera Nair
9
- * — Empty cart (items: []) — Amit Sharma
5
+ * â€" Multi-item cart (cross-store, mixed categories) â€" Rahul Sharma
6
+ * â€" Single-item cart â€" Priya Patel
7
+ * â€" Cart with auction item â€" Arjun Singh
8
+ * â€" Cart with quantity > 1 â€" Meera Nair
9
+ * â€" Empty cart (items: []) â€" Amit Sharma
10
10
  *
11
- * Cart document ID = userId (O(1) lookup — see cart.ts schema).
11
+ * Cart document ID = userId (O(1) lookup â€" see cart.ts schema).
12
12
  *
13
13
  * All FK references:
14
- * userId → users/{uid} (see users-seed-data.ts)
15
- * items[].productId → products/{id} (see products-standard/auctions-seed-data.ts)
16
- * items[].storeId → stores/{id} (see stores-seed-data.ts)
14
+ * userId â†' users/{uid} (see users-seed-data.ts)
15
+ * items[].productId â†' products/{id} (see products-standard/auctions-seed-data.ts)
16
+ * items[].storeId â†' stores/{id} (see stores-seed-data.ts)
17
17
  */
18
18
  import type { CartDocument } from "../features/cart/schemas";
19
19
  export declare const cartsSeedData: CartDocument[];