@mohasinac/appkit 2.8.4 → 2.8.6

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 (128) hide show
  1. package/dist/_internal/client/features/layout/SidebarCollapseToggle.js +2 -0
  2. package/dist/_internal/server/features/checkout/actions.js +2 -1
  3. package/dist/_internal/server/features/grouped/data.js +9 -8
  4. package/dist/_internal/server/features/products/data.js +2 -1
  5. package/dist/_internal/server/features/refunds/actions.js +2 -1
  6. package/dist/_internal/server/features/seo/sitemap.js +2 -1
  7. package/dist/_internal/server/jobs/core/countersReconcile.js +4 -4
  8. package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
  9. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
  10. package/dist/_internal/shared/listing-types/action-tracker.js +0 -2
  11. package/dist/constants/field-names.d.ts +3 -0
  12. package/dist/constants/field-names.js +3 -0
  13. package/dist/core/unit-of-work.js +0 -1
  14. package/dist/features/account/components/NotificationBell.js +1 -0
  15. package/dist/features/account/components/UserOffersPanel.js +1 -0
  16. package/dist/features/account/components/UserSidebar.js +3 -1
  17. package/dist/features/admin/components/AdminCarouselEditorView.js +3 -1
  18. package/dist/features/admin/components/AdminSidebar.js +3 -1
  19. package/dist/features/admin/components/AdminSiteSettingsView.js +3 -1
  20. package/dist/features/admin/components/AdminSupportTicketDetailView.js +0 -3
  21. package/dist/features/admin/components/DashboardStats.js +5 -1
  22. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +3 -1
  23. package/dist/features/admin/components/analytics/AdminStatCard.js +5 -1
  24. package/dist/features/admin/hooks/useChat.js +1 -0
  25. package/dist/features/admin/repository/chat.repository.js +7 -6
  26. package/dist/features/auctions/components/AuctionBidsTable.js +5 -1
  27. package/dist/features/auctions/components/AuctionBottomActions.js +3 -4
  28. package/dist/features/auctions/repository/bid.repository.js +12 -12
  29. package/dist/features/auth/hooks/useAuth.js +1 -0
  30. package/dist/features/blog/actions/blog-actions.d.ts +2 -2
  31. package/dist/features/blog/components/BlogFeaturedCard.js +3 -1
  32. package/dist/features/blog/components/BlogListView.js +5 -1
  33. package/dist/features/blog/components/BlogPostView.js +3 -1
  34. package/dist/features/blog/schemas/index.d.ts +1 -1
  35. package/dist/features/cart/components/CartDrawer.js +3 -1
  36. package/dist/features/cart/repository/cart.repository.js +2 -1
  37. package/dist/features/categories/components/BrandDetailPageView.js +5 -1
  38. package/dist/features/categories/components/CategoryDetailPageView.js +3 -1
  39. package/dist/features/categories/components/CategoryGrid.js +5 -1
  40. package/dist/features/categories/components/CategoryTableColumns.js +6 -2
  41. package/dist/features/categories/components/CategoryTree.js +3 -1
  42. package/dist/features/categories/components/ConcernCard.js +3 -1
  43. package/dist/features/categories/repository/categories.repository.js +26 -25
  44. package/dist/features/categories/schemas/firestore.d.ts +1 -0
  45. package/dist/features/categories/schemas/firestore.js +1 -0
  46. package/dist/features/categories/schemas/index.d.ts +10 -10
  47. package/dist/features/collections/components/CollectionCard.js +3 -1
  48. package/dist/features/events/components/EventCard.js +3 -1
  49. package/dist/features/events/components/EventParticipateView.js +2 -1
  50. package/dist/features/events/schemas/index.d.ts +3 -3
  51. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  52. package/dist/features/faq/repository/faqs.repository.js +21 -20
  53. package/dist/features/faq/schemas/index.d.ts +2 -2
  54. package/dist/features/forms/Slider.js +3 -1
  55. package/dist/features/history/hooks/useHistory.js +1 -0
  56. package/dist/features/homepage/components/AdSlot.js +6 -2
  57. package/dist/features/homepage/components/AdvertisementBanner.js +3 -1
  58. package/dist/features/homepage/components/BeforeAfterCard.js +5 -1
  59. package/dist/features/homepage/components/CustomCardsSection.js +5 -1
  60. package/dist/features/homepage/components/HowItWorksSection.js +3 -1
  61. package/dist/features/homepage/components/NewsletterBanner.js +6 -2
  62. package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -1
  63. package/dist/features/homepage/components/StatsCounterSection.js +3 -1
  64. package/dist/features/homepage/components/TrustFeaturesSection.js +3 -1
  65. package/dist/features/homepage/repository/carousel.repository.js +8 -7
  66. package/dist/features/homepage/repository/carousels.repository.js +2 -1
  67. package/dist/features/homepage/repository/homepage-sections.repository.js +6 -5
  68. package/dist/features/layout/AppLayoutShell.js +3 -1
  69. package/dist/features/layout/BottomActionsContext.js +1 -3
  70. package/dist/features/layout/BottomNavbar.js +1 -1
  71. package/dist/features/media/MediaLightbox.js +9 -3
  72. package/dist/features/media/modals/ImageEditor.js +6 -2
  73. package/dist/features/media/upload/MediaUploadField.js +1 -1
  74. package/dist/features/messages/hooks/useConversation.js +2 -0
  75. package/dist/features/messages/hooks/useConversations.js +1 -0
  76. package/dist/features/messages/repository/conversations.repository.js +5 -4
  77. package/dist/features/orders/components/OrdersList.js +3 -1
  78. package/dist/features/orders/repository/orders.repository.js +13 -13
  79. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
  80. package/dist/features/products/components/CompareOverlay.js +5 -1
  81. package/dist/features/products/components/FeatureBadge.js +3 -1
  82. package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
  83. package/dist/features/products/components/ProductGrid.js +3 -1
  84. package/dist/features/products/repository/product-features.repository.js +7 -6
  85. package/dist/features/products/repository/product-templates.repository.js +4 -3
  86. package/dist/features/products/repository/products.repository.js +4 -4
  87. package/dist/features/promotions/repository/claimed-coupons.repository.js +2 -1
  88. package/dist/features/promotions/repository/coupons.repository.js +4 -4
  89. package/dist/features/reviews/components/ReviewDetailShell.js +8 -2
  90. package/dist/features/reviews/components/ReviewModal.js +5 -1
  91. package/dist/features/reviews/components/ReviewSummary.js +3 -1
  92. package/dist/features/reviews/components/ReviewsList.js +5 -1
  93. package/dist/features/reviews/repository/reviews.repository.js +2 -2
  94. package/dist/features/scams/repository/scammer.repository.js +3 -3
  95. package/dist/features/search/components/Search.js +14 -1
  96. package/dist/features/seller/components/PhysicalLocationModal.js +1 -1
  97. package/dist/features/seller/components/SellerAddressesView.js +2 -1
  98. package/dist/features/seller/components/SellerBidsView.js +3 -1
  99. package/dist/features/seller/components/SellerCouponEditorView.js +3 -1
  100. package/dist/features/seller/components/SellerOffersPanel.js +1 -0
  101. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -0
  102. package/dist/features/seller/components/SellerProductsView.js +5 -1
  103. package/dist/features/seller/components/SellerReviewsView.js +1 -0
  104. package/dist/features/seller/components/SellerShippingConfigsView.js +1 -0
  105. package/dist/features/seller/components/SellerSidebar.js +12 -4
  106. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -0
  107. package/dist/features/seller/components/SellerTemplatesView.js +1 -0
  108. package/dist/features/shell/FormShell.js +10 -2
  109. package/dist/features/shell/QuickFormDrawer.js +5 -2
  110. package/dist/features/stores/components/StoreHeader.js +5 -1
  111. package/dist/features/support/repository/support.repository.js +8 -7
  112. package/dist/features/wishlist/components/WishlistPage.js +3 -1
  113. package/dist/providers/db-firebase/admin.js +0 -1
  114. package/dist/seed/products-auctions-seed-data.js +107 -0
  115. package/dist/ui/DataTable.js +6 -2
  116. package/dist/ui/components/AvatarDisplay.js +3 -1
  117. package/dist/ui/components/BackgroundRenderer.js +4 -2
  118. package/dist/ui/components/Card.js +6 -2
  119. package/dist/ui/components/ImageGallery.js +3 -1
  120. package/dist/ui/components/ImageLightbox.js +3 -1
  121. package/dist/ui/components/PasswordStrengthIndicator.js +3 -1
  122. package/dist/ui/components/Progress.js +6 -2
  123. package/dist/ui/components/RowActionMenu.js +3 -1
  124. package/dist/ui/components/SiteLogo.js +7 -1
  125. package/dist/ui/components/Skeleton.js +3 -1
  126. package/dist/ui/components/Slider.js +3 -1
  127. package/dist/ui/components/TabStrip.js +3 -1
  128. package/package.json +1 -1
@@ -14,6 +14,7 @@ export function useChat(chatId, options) {
14
14
  const tokenExpiresAtRef = useRef(0);
15
15
  const unsubscribeRef = useRef(null);
16
16
  const connectAndSubscribe = useCallback(async () => {
17
+ // toast-intentionally-silent — error stored in setError() for UI inline render
17
18
  if (!chatId)
18
19
  return;
19
20
  setIsLoading(true);
@@ -22,6 +22,7 @@ import { getAdminRealtimeDb } from "../../../providers/db-firebase";
22
22
  import { BaseRepository } from "../../../providers/db-firebase";
23
23
  import { prepareForFirestore } from "../../../providers/db-firebase";
24
24
  import { DatabaseError } from "../../../errors";
25
+ import { CONVERSATION_FIELDS, STORE_FIELDS } from "../../../constants/field-names";
25
26
  import { CHAT_ROOM_COLLECTION } from "../schemas";
26
27
  import { encryptPiiFields, decryptPiiFields, CHAT_PII_FIELDS, } from "../../../security";
27
28
  export { CHAT_ROOM_COLLECTION } from "../schemas";
@@ -72,11 +73,11 @@ class ChatRepository extends BaseRepository {
72
73
  try {
73
74
  const [asBuyer, asSeller] = await Promise.all([
74
75
  this.getCollection()
75
- .where("buyerId", "==", userId)
76
+ .where(CONVERSATION_FIELDS.BUYER_ID, "==", userId)
76
77
  .where("adminDeleted", "==", false)
77
78
  .get(),
78
79
  this.getCollection()
79
- .where("ownerId", "==", userId)
80
+ .where(STORE_FIELDS.OWNER_ID, "==", userId)
80
81
  .where("adminDeleted", "==", false)
81
82
  .get(),
82
83
  ]);
@@ -101,14 +102,14 @@ class ChatRepository extends BaseRepository {
101
102
  try {
102
103
  const [asBuyer, asSeller] = await Promise.all([
103
104
  this.getCollection()
104
- .where("buyerId", "==", userId)
105
+ .where(CONVERSATION_FIELDS.BUYER_ID, "==", userId)
105
106
  .where("adminDeleted", "==", false)
106
- .orderBy("updatedAt", "desc")
107
+ .orderBy(CONVERSATION_FIELDS.UPDATED_AT, "desc")
107
108
  .get(),
108
109
  this.getCollection()
109
- .where("ownerId", "==", userId)
110
+ .where(STORE_FIELDS.OWNER_ID, "==", userId)
110
111
  .where("adminDeleted", "==", false)
111
- .orderBy("updatedAt", "desc")
112
+ .orderBy(CONVERSATION_FIELDS.UPDATED_AT, "desc")
112
113
  .get(),
113
114
  ]);
114
115
  const seen = new Set();
@@ -54,7 +54,11 @@ function AuctionRow({ auction, portal, }) {
54
54
  const sorted = useMemo(() => [...auction.bids].sort((a, b) => b.bidAmount - a.bidAmount), [auction.bids]);
55
55
  const highest = sorted[0]?.bidAmount ?? 0;
56
56
  const isWinning = auction.bids.some((b) => b.isWinning);
57
- return (_jsxs(Div, { className: `border border-[var(--appkit-color-border)] rounded-xl ${__O.hidden} bg-[var(--appkit-color-surface)] shadow-sm`, children: [_jsxs("button", { type: "button", onClick: () => setExpanded((v) => !v), className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-[var(--appkit-color-border-subtle)] transition-colors text-left", "aria-expanded": expanded, children: [_jsx(ChevronRight, { className: `shrink-0 text-[var(--appkit-color-text-muted)] transition-transform ${expanded ? "rotate-90" : ""}`, size: 16 }), _jsx(Div, { className: "flex-1 min-w-0", children: _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text)] line-clamp-1", children: auction.productTitle }) }), _jsxs(Row, { gap: "sm", className: "shrink-0", children: [isWinning && (_jsx(Badge, { variant: "active", children: "Winning" })), _jsxs(Text, { variant: "secondary", className: "text-xs", children: [auction.bids.length, " bid", auction.bids.length !== 1 ? "s" : ""] }), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text)]", children: paise(highest) })] })] }), expanded && (_jsxs(Div, { className: "border-t border-[var(--appkit-color-border)]", children: [_jsxs("div", { className: "grid text-xs font-medium text-[var(--appkit-color-text-muted)] uppercase tracking-wide px-4 py-2 border-b border-[var(--appkit-color-border-subtle)]", style: { gridTemplateColumns: portal === "buyer" ? "1fr auto auto" : "1fr 1fr auto auto" }, children: [_jsx("span", { children: portal === "buyer" ? "Amount" : "Bidder" }), portal !== "buyer" && _jsx("span", { children: "Amount" }), _jsx("span", { children: "Status" }), _jsx("span", { className: "text-right", children: "Time" })] }), sorted.map((bid) => (_jsxs("div", { className: "grid items-center px-4 py-2.5 border-b border-[var(--appkit-color-border-subtle)] last:border-0 hover:bg-[var(--appkit-color-border-subtle)] transition-colors", style: { gridTemplateColumns: portal === "buyer" ? "1fr auto auto" : "1fr 1fr auto auto" }, children: [portal !== "buyer" && (_jsx(Text, { className: "text-sm text-[var(--appkit-color-text)] truncate pr-3", children: bid.userName || bid.userId })), _jsx(Text, { className: "text-sm font-medium text-[var(--appkit-color-text)]", children: paise(bid.bidAmount) }), _jsx(Badge, { variant: STATUS_VARIANT[bid.status] ?? "pending", className: "capitalize", children: bid.status }), _jsx(Text, { variant: "secondary", className: "text-xs text-right", children: relDate(bid.bidDate) })] }, bid.id)))] }))] }));
57
+ return (_jsxs(Div, { className: `border border-[var(--appkit-color-border)] rounded-xl ${__O.hidden} bg-[var(--appkit-color-surface)] shadow-sm`, children: [_jsxs("button", { type: "button", onClick: () => setExpanded((v) => !v), className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-[var(--appkit-color-border-subtle)] transition-colors text-left", "aria-expanded": expanded, children: [_jsx(ChevronRight, { className: `shrink-0 text-[var(--appkit-color-text-muted)] transition-transform ${expanded ? "rotate-90" : ""}`, size: 16 }), _jsx(Div, { className: "flex-1 min-w-0", children: _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text)] line-clamp-1", children: auction.productTitle }) }), _jsxs(Row, { gap: "sm", className: "shrink-0", children: [isWinning && (_jsx(Badge, { variant: "active", children: "Winning" })), _jsxs(Text, { variant: "secondary", className: "text-xs", children: [auction.bids.length, " bid", auction.bids.length !== 1 ? "s" : ""] }), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text)]", children: paise(highest) })] })] }), expanded && (_jsxs(Div, { className: "border-t border-[var(--appkit-color-border)]", children: [_jsxs("div", { className: "grid text-xs font-medium text-[var(--appkit-color-text-muted)] uppercase tracking-wide px-4 py-2 border-b border-[var(--appkit-color-border-subtle)]",
58
+ // audit-inline-style-ok: runtime grid template
59
+ style: { gridTemplateColumns: portal === "buyer" ? "1fr auto auto" : "1fr 1fr auto auto" }, children: [_jsx("span", { children: portal === "buyer" ? "Amount" : "Bidder" }), portal !== "buyer" && _jsx("span", { children: "Amount" }), _jsx("span", { children: "Status" }), _jsx("span", { className: "text-right", children: "Time" })] }), sorted.map((bid) => (_jsxs("div", { className: "grid items-center px-4 py-2.5 border-b border-[var(--appkit-color-border-subtle)] last:border-0 hover:bg-[var(--appkit-color-border-subtle)] transition-colors",
60
+ // audit-inline-style-ok: runtime grid template
61
+ style: { gridTemplateColumns: portal === "buyer" ? "1fr auto auto" : "1fr 1fr auto auto" }, children: [portal !== "buyer" && (_jsx(Text, { className: "text-sm text-[var(--appkit-color-text)] truncate pr-3", children: bid.userName || bid.userId })), _jsx(Text, { className: "text-sm font-medium text-[var(--appkit-color-text)]", children: paise(bid.bidAmount) }), _jsx(Badge, { variant: STATUS_VARIANT[bid.status] ?? "pending", className: "capitalize", children: bid.status }), _jsx(Text, { variant: "secondary", className: "text-xs text-right", children: relDate(bid.bidDate) })] }, bid.id)))] }))] }));
58
62
  }
59
63
  export function AuctionBidsTable({ bids, portal = "buyer", emptyLabel = "No bids found.", }) {
60
64
  const auctions = useMemo(() => groupByAuction(bids), [bids]);
@@ -1,16 +1,15 @@
1
1
  "use client";
2
2
  import { useBottomActions } from "../../layout/hooks/useBottomActions";
3
3
  import { formatCurrency } from "../../../utils/number.formatter";
4
- import { ACTION_ID } from "../../products/constants/action-defs";
4
+ import { ACTION_ID, ACTION_META } from "../../products/constants/action-defs";
5
5
  export function AuctionBottomActions({ currentBid, currency, bidCount, isEnded, }) {
6
+ const placeBidMeta = ACTION_META[ACTION_ID.PLACE_BID];
6
7
  useBottomActions(isEnded
7
8
  ? {}
8
9
  : {
9
10
  actions: [
10
11
  {
11
- id: ACTION_ID.PLACE_BID,
12
- label: "Place Bid",
13
- variant: "primary",
12
+ ...placeBidMeta,
14
13
  onClick: () => {
15
14
  document
16
15
  .getElementById("auction-bid-form")
@@ -63,7 +63,7 @@ export class BidRepository extends BaseRepository {
63
63
  let query = this.db
64
64
  .collection(this.collection)
65
65
  .where(BID_FIELDS.USER_ID, "==", userId)
66
- .orderBy("createdAt", "desc")
66
+ .orderBy(BID_FIELDS.CREATED_AT, "desc")
67
67
  .limit(pageSize + 1);
68
68
  if (startAfterDoc)
69
69
  query = query.startAfter(startAfterDoc);
@@ -86,7 +86,7 @@ export class BidRepository extends BaseRepository {
86
86
  .collection(this.collection)
87
87
  .where(BID_FIELDS.PRODUCT_ID, "==", productId)
88
88
  .where(BID_FIELDS.STATUS, "==", "active")
89
- .orderBy("bidAmount", "desc")
89
+ .orderBy(BID_FIELDS.BID_AMOUNT, "desc")
90
90
  .get();
91
91
  return snapshot.docs.map((doc) => ({
92
92
  id: doc.id,
@@ -169,9 +169,9 @@ export class BidRepository extends BaseRepository {
169
169
  try {
170
170
  const snapshot = await this.db
171
171
  .collection(this.collection)
172
- .where("productId", "==", productId)
173
- .where("status", "==", "active")
174
- .orderBy("bidAmount", "desc")
172
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
173
+ .where(BID_FIELDS.STATUS, "==", "active")
174
+ .orderBy(BID_FIELDS.BID_AMOUNT, "desc")
175
175
  .limit(1)
176
176
  .get();
177
177
  if (snapshot.empty) {
@@ -192,8 +192,8 @@ export class BidRepository extends BaseRepository {
192
192
  try {
193
193
  const snapshot = await this.db
194
194
  .collection(this.collection)
195
- .where("productId", "==", productId)
196
- .orderBy("bidAmount", "desc")
195
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
196
+ .orderBy(BID_FIELDS.BID_AMOUNT, "desc")
197
197
  .get();
198
198
  return snapshot.docs.map((doc) => this.mapDoc(doc));
199
199
  }
@@ -230,7 +230,7 @@ export class BidRepository extends BaseRepository {
230
230
  // Set all bids for this product to not winning
231
231
  const allBidsSnapshot = await this.db
232
232
  .collection(this.collection)
233
- .where("productId", "==", productId)
233
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
234
234
  .get();
235
235
  allBidsSnapshot.docs.forEach((doc) => {
236
236
  batch.update(doc.ref, {
@@ -260,7 +260,7 @@ export class BidRepository extends BaseRepository {
260
260
  const batch = this.db.batch();
261
261
  const bidsSnapshot = await this.db
262
262
  .collection(this.collection)
263
- .where("productId", "==", productId)
263
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
264
264
  .get();
265
265
  bidsSnapshot.docs.forEach((doc) => {
266
266
  const bid = doc.data();
@@ -283,7 +283,7 @@ export class BidRepository extends BaseRepository {
283
283
  const batch = this.db.batch();
284
284
  const bidsSnapshot = await this.db
285
285
  .collection(this.collection)
286
- .where("productId", "==", productId)
286
+ .where(BID_FIELDS.PRODUCT_ID, "==", productId)
287
287
  .get();
288
288
  bidsSnapshot.docs.forEach((doc) => {
289
289
  batch.update(doc.ref, {
@@ -303,7 +303,7 @@ export class BidRepository extends BaseRepository {
303
303
  */
304
304
  async countByProduct(productId) {
305
305
  try {
306
- return await getFirestoreCount(this.db.collection(this.collection).where("productId", "==", productId));
306
+ return await getFirestoreCount(this.db.collection(this.collection).where(BID_FIELDS.PRODUCT_ID, "==", productId));
307
307
  }
308
308
  catch (error) {
309
309
  throw new DatabaseError(`Failed to count bids for product: ${productId}`, error);
@@ -314,7 +314,7 @@ export class BidRepository extends BaseRepository {
314
314
  */
315
315
  async countByUser(userId) {
316
316
  try {
317
- return await getFirestoreCount(this.db.collection(this.collection).where("userId", "==", userId));
317
+ return await getFirestoreCount(this.db.collection(this.collection).where(BID_FIELDS.USER_ID, "==", userId));
318
318
  }
319
319
  catch (error) {
320
320
  throw new DatabaseError(`Failed to count bids for user: ${userId}`, error);
@@ -119,6 +119,7 @@ export function useGoogleLogin(options) {
119
119
  return () => window.removeEventListener("message", handleMessage);
120
120
  }, []); // mount once — uses refs, no stale closure risk
121
121
  const mutate = useCallback(async () => {
122
+ // toast-intentionally-silent — errors surfaced via onErrorRef.current() callback
122
123
  calledRef.current = false; // reset for each new auth flow
123
124
  const popup = window.open(`${window.location.origin}/auth.html`, "oauth_google", "width=500,height=660,left=400,top=100");
124
125
  if (!popup) {
@@ -216,6 +216,7 @@ export declare const updateBlogPostSchema: z.ZodObject<{
216
216
  content?: string | undefined;
217
217
  isFeatured?: boolean | undefined;
218
218
  publishedAt?: string | undefined;
219
+ excerpt?: string | undefined;
219
220
  coverImage?: {
220
221
  url: string;
221
222
  type: "image" | "video" | "file";
@@ -225,7 +226,6 @@ export declare const updateBlogPostSchema: z.ZodObject<{
225
226
  url: string;
226
227
  type: "image";
227
228
  } | null | undefined;
228
- excerpt?: string | undefined;
229
229
  authorId?: string | undefined;
230
230
  authorName?: string | undefined;
231
231
  readTimeMinutes?: number | undefined;
@@ -253,13 +253,13 @@ export declare const updateBlogPostSchema: z.ZodObject<{
253
253
  content?: string | undefined;
254
254
  isFeatured?: boolean | undefined;
255
255
  publishedAt?: string | undefined;
256
+ excerpt?: string | undefined;
256
257
  coverImage?: string | {
257
258
  url: string;
258
259
  type: "image" | "video" | "file";
259
260
  alt?: string | undefined;
260
261
  thumbnailUrl?: string | undefined;
261
262
  } | null | undefined;
262
- excerpt?: string | undefined;
263
263
  authorId?: string | undefined;
264
264
  authorName?: string | undefined;
265
265
  readTimeMinutes?: number | undefined;
@@ -31,5 +31,7 @@ export function BlogFeaturedCard({ post, href, labels = {}, className = "", sele
31
31
  day: "numeric",
32
32
  })
33
33
  : "";
34
- return (_jsxs(Article, { className: `group relative flex h-full flex-col overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm hover:shadow-md transition-shadow duration-200 ${isSelected ? "ring-2 ring-primary outline outline-2 outline-primary" : ""} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(post.id, !isSelected); }, label: isSelected ? "Deselect post" : "Select post", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsxs(TextLink, { href: href, className: "flex h-full flex-col", children: [_jsx(Div, { className: `aspect-video ${__O.hidden} flex-shrink-0`, children: coverImageUrl ? (_jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${coverImageUrl})` } })) : (_jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-gradient-to-br from-zinc-200 via-zinc-100 to-zinc-300 dark:from-slate-800 dark:via-slate-700 dark:to-slate-900" })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Row, { className: "gap-1.5 mb-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-block px-2 py-0.5 rounded-full capitalize ${CATEGORY_BADGE[post.category] ?? "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"}`, children: post.category }), post.isFeatured && (_jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: labels.featuredBadge ?? "Featured" }))] }), _jsx(Heading, { level: 3, className: `font-semibold text-neutral-900 dark:text-zinc-100 text-base leading-snug mb-1 ${THEME_CONSTANTS.utilities.textClamp2}`, children: safeTitle }), post.excerpt && (_jsx(Text, { className: `text-neutral-500 dark:text-zinc-400 text-sm ${THEME_CONSTANTS.utilities.textClamp2} mb-3`, children: post.excerpt })), _jsxs(Row, { className: "mt-auto gap-3 text-xs text-zinc-400 dark:text-zinc-400 flex-wrap", children: [post.authorName && (_jsx(Span, { children: safeDisplayName(post.authorName, "Author") })), post.readTimeMinutes != null && (_jsxs(Span, { children: [post.readTimeMinutes, " ", labels.readTime ?? "min read"] })), date && _jsx(Span, { children: date })] })] })] })] }));
34
+ return (_jsxs(Article, { className: `group relative flex h-full flex-col overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm hover:shadow-md transition-shadow duration-200 ${isSelected ? "ring-2 ring-primary outline outline-2 outline-primary" : ""} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(post.id, !isSelected); }, label: isSelected ? "Deselect post" : "Select post", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsxs(TextLink, { href: href, className: "flex h-full flex-col", children: [_jsx(Div, { className: `aspect-video ${__O.hidden} flex-shrink-0`, children: coverImageUrl ? (_jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105",
35
+ // audit-inline-style-ok: dynamic image URL
36
+ style: { backgroundImage: `url(${coverImageUrl})` } })) : (_jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-gradient-to-br from-zinc-200 via-zinc-100 to-zinc-300 dark:from-slate-800 dark:via-slate-700 dark:to-slate-900" })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Row, { className: "gap-1.5 mb-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-block px-2 py-0.5 rounded-full capitalize ${CATEGORY_BADGE[post.category] ?? "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"}`, children: post.category }), post.isFeatured && (_jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: labels.featuredBadge ?? "Featured" }))] }), _jsx(Heading, { level: 3, className: `font-semibold text-neutral-900 dark:text-zinc-100 text-base leading-snug mb-1 ${THEME_CONSTANTS.utilities.textClamp2}`, children: safeTitle }), post.excerpt && (_jsx(Text, { className: `text-neutral-500 dark:text-zinc-400 text-sm ${THEME_CONSTANTS.utilities.textClamp2} mb-3`, children: post.excerpt })), _jsxs(Row, { className: "mt-auto gap-3 text-xs text-zinc-400 dark:text-zinc-400 flex-wrap", children: [post.authorName && (_jsx(Span, { children: safeDisplayName(post.authorName, "Author") })), post.readTimeMinutes != null && (_jsxs(Span, { children: [post.readTimeMinutes, " ", labels.readTime ?? "min read"] })), date && _jsx(Span, { children: date })] })] })] })] }));
35
37
  }
@@ -26,7 +26,11 @@ export function BlogCard({ post, href, onClick, className = "" }) {
26
26
  const isInteractive = !!(href || onClick);
27
27
  const card = (_jsxs(Article, { role: onClick && !href ? "button" : undefined, tabIndex: onClick && !href ? 0 : undefined, onKeyDown: onClick && !href
28
28
  ? (e) => (e.key === "Enter" || e.key === " ") && onClick(post)
29
- : undefined, onClick: onClick && !href ? () => onClick(post) : undefined, className: `group flex flex-col h-full overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm transition hover:shadow-md ${isInteractive ? "cursor-pointer" : ""} ${className}`, children: [_jsx(Div, { className: `aspect-video w-full ${__O.hidden} bg-neutral-100 dark:bg-slate-800 flex-shrink-0`, children: coverImageUrl ? (_jsx(Div, { role: "img", "aria-label": post.title, className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${coverImageUrl})` } })) : (_jsx(Div, { className: "h-full w-full bg-gradient-to-br from-zinc-200 via-zinc-100 to-zinc-300 dark:from-slate-800 dark:via-slate-700 dark:to-slate-900 flex items-center justify-center", children: _jsx(Span, { className: "text-4xl opacity-30", "aria-hidden": "true", children: "\u270D\uFE0F" }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p5}`, children: [_jsxs(Row, { className: "mb-2 gap-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "medium", className: "rounded-full bg-primary/10 px-2 py-0.5 capitalize text-primary", children: post.category }), post.isFeatured && (_jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: "Featured" })), post.readTimeMinutes && (_jsxs(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400", children: [post.readTimeMinutes, " min read"] }))] }), _jsx(Heading, { level: 3, className: `${THEME_CONSTANTS.utilities.textClamp2} text-base font-semibold text-neutral-900 dark:text-zinc-100 group-hover:text-primary`, children: post.title }), post.excerpt && (_jsx(Text, { className: `mt-2 ${THEME_CONSTANTS.utilities.textClamp3} flex-1 text-sm text-neutral-500 dark:text-zinc-400`, children: post.excerpt })), _jsxs(Row, { className: "mt-auto pt-3 gap-3", children: [post.authorAvatar ? (_jsx(Div, { role: "img", "aria-label": post.authorName ?? "author", className: "h-7 w-7 flex-shrink-0 rounded-full bg-center bg-cover", style: { backgroundImage: `url(${post.authorAvatar})` } })) : post.authorName ? (_jsx(Div, { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-bold text-primary", children: post.authorName.charAt(0).toUpperCase() })) : null, _jsxs(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400 min-w-0", children: [post.authorName && (_jsx(Span, { weight: "medium", className: "text-neutral-700 dark:text-zinc-300", children: safeDisplayName(post.authorName, "Author") })), date && _jsxs(Span, { className: "ml-1 text-neutral-400", children: ["\u00B7 ", date] })] })] })] })] }));
29
+ : undefined, onClick: onClick && !href ? () => onClick(post) : undefined, className: `group flex flex-col h-full overflow-hidden rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 shadow-sm transition hover:shadow-md ${isInteractive ? "cursor-pointer" : ""} ${className}`, children: [_jsx(Div, { className: `aspect-video w-full ${__O.hidden} bg-neutral-100 dark:bg-slate-800 flex-shrink-0`, children: coverImageUrl ? (_jsx(Div, { role: "img", "aria-label": post.title, className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105",
30
+ // audit-inline-style-ok: dynamic image URL
31
+ style: { backgroundImage: `url(${coverImageUrl})` } })) : (_jsx(Div, { className: "h-full w-full bg-gradient-to-br from-zinc-200 via-zinc-100 to-zinc-300 dark:from-slate-800 dark:via-slate-700 dark:to-slate-900 flex items-center justify-center", children: _jsx(Span, { className: "text-4xl opacity-30", "aria-hidden": "true", children: "\u270D\uFE0F" }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p5}`, children: [_jsxs(Row, { className: "mb-2 gap-2 flex-wrap", children: [_jsx(Span, { size: "xs", weight: "medium", className: "rounded-full bg-primary/10 px-2 py-0.5 capitalize text-primary", children: post.category }), post.isFeatured && (_jsx(Span, { size: "xs", weight: "medium", className: CLS_FEATURED_BADGE, children: "Featured" })), post.readTimeMinutes && (_jsxs(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400", children: [post.readTimeMinutes, " min read"] }))] }), _jsx(Heading, { level: 3, className: `${THEME_CONSTANTS.utilities.textClamp2} text-base font-semibold text-neutral-900 dark:text-zinc-100 group-hover:text-primary`, children: post.title }), post.excerpt && (_jsx(Text, { className: `mt-2 ${THEME_CONSTANTS.utilities.textClamp3} flex-1 text-sm text-neutral-500 dark:text-zinc-400`, children: post.excerpt })), _jsxs(Row, { className: "mt-auto pt-3 gap-3", children: [post.authorAvatar ? (_jsx(Div, { role: "img", "aria-label": post.authorName ?? "author", className: "h-7 w-7 flex-shrink-0 rounded-full bg-center bg-cover",
32
+ // audit-inline-style-ok: dynamic image URL
33
+ style: { backgroundImage: `url(${post.authorAvatar})` } })) : post.authorName ? (_jsx(Div, { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-bold text-primary", children: post.authorName.charAt(0).toUpperCase() })) : null, _jsxs(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400 min-w-0", children: [post.authorName && (_jsx(Span, { weight: "medium", className: "text-neutral-700 dark:text-zinc-300", children: safeDisplayName(post.authorName, "Author") })), date && _jsxs(Span, { className: "ml-1 text-neutral-400", children: ["\u00B7 ", date] })] })] })] })] }));
30
34
  if (href) {
31
35
  return (_jsx(Link, { href: href, className: "block h-full", children: card }));
32
36
  }
@@ -53,5 +53,7 @@ export function BlogPostView({ slug, initialData, labels = {}, renderImage, rend
53
53
  })
54
54
  : "";
55
55
  const coverImageUrl = getMediaUrl(post.coverImage);
56
- return (_jsxs(Div, { className: `min-h-screen ${className}`, children: [coverImageUrl && (_jsxs(Div, { className: `relative h-72 md:h-96 ${__O.hidden}`, children: [renderImage ? (renderImage(post)) : (_jsx(Div, { role: "img", "aria-label": post.title, className: "h-full w-full bg-cover bg-center", style: { backgroundImage: `url(${coverImageUrl})` } })), _jsx(Div, { className: "absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" })] })), _jsxs(Div, { className: "max-w-3xl mx-auto px-4 py-12", children: [renderBlogPostHeader(post, date, labels), post.tags && post.tags.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mb-8", children: post.tags.map((tag) => (_jsxs(Link, { href: `${String(ROUTES.PUBLIC.BLOG)}?tags=${encodeURIComponent(tag)}`, className: "inline-block px-3 py-1 rounded-full bg-neutral-100 dark:bg-zinc-800 hover:bg-primary/10 text-zinc-600 dark:text-zinc-400 hover:text-primary text-xs font-medium transition-colors", children: ["#", tag] }, tag))) })), renderAuthorBio && _jsx(Div, { className: "mb-6", children: renderAuthorBio(post) }), _jsx(Div, { surface: "card", padding: "xl", className: "mb-12", children: renderContent ? renderContent(post) : (_jsx(RichText, { html: normalizeRichTextHtml(post.content ?? ""), proseClass: "prose max-w-none dark:prose-invert" })) }), renderBlogPostRelated(related, labels, renderRelatedCard), renderBackButton && _jsx(Div, { className: "mt-10 pt-8 border-t border-zinc-200 dark:border-zinc-700", children: renderBackButton() })] })] }));
56
+ return (_jsxs(Div, { className: `min-h-screen ${className}`, children: [coverImageUrl && (_jsxs(Div, { className: `relative h-72 md:h-96 ${__O.hidden}`, children: [renderImage ? (renderImage(post)) : (_jsx(Div, { role: "img", "aria-label": post.title, className: "h-full w-full bg-cover bg-center",
57
+ // audit-inline-style-ok: dynamic image URL
58
+ style: { backgroundImage: `url(${coverImageUrl})` } })), _jsx(Div, { className: "absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" })] })), _jsxs(Div, { className: "max-w-3xl mx-auto px-4 py-12", children: [renderBlogPostHeader(post, date, labels), post.tags && post.tags.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mb-8", children: post.tags.map((tag) => (_jsxs(Link, { href: `${String(ROUTES.PUBLIC.BLOG)}?tags=${encodeURIComponent(tag)}`, className: "inline-block px-3 py-1 rounded-full bg-neutral-100 dark:bg-zinc-800 hover:bg-primary/10 text-zinc-600 dark:text-zinc-400 hover:text-primary text-xs font-medium transition-colors", children: ["#", tag] }, tag))) })), renderAuthorBio && _jsx(Div, { className: "mb-6", children: renderAuthorBio(post) }), _jsx(Div, { surface: "card", padding: "xl", className: "mb-12", children: renderContent ? renderContent(post) : (_jsx(RichText, { html: normalizeRichTextHtml(post.content ?? ""), proseClass: "prose max-w-none dark:prose-invert" })) }), renderBlogPostRelated(related, labels, renderRelatedCard), renderBackButton && _jsx(Div, { className: "mt-10 pt-8 border-t border-zinc-200 dark:border-zinc-700", children: renderBackButton() })] })] }));
57
59
  }
@@ -180,6 +180,7 @@ export declare const blogPostSchema: z.ZodObject<{
180
180
  content?: string | undefined;
181
181
  isFeatured?: boolean | undefined;
182
182
  publishedAt?: string | undefined;
183
+ excerpt?: string | undefined;
183
184
  coverImage?: string | {
184
185
  url: string;
185
186
  type: "image" | "video" | "file";
@@ -188,7 +189,6 @@ export declare const blogPostSchema: z.ZodObject<{
188
189
  source?: "upload" | "youtube" | "external" | undefined;
189
190
  youtubeId?: string | undefined;
190
191
  } | null | undefined;
191
- excerpt?: string | undefined;
192
192
  authorId?: string | undefined;
193
193
  authorName?: string | undefined;
194
194
  readTimeMinutes?: number | undefined;
@@ -12,7 +12,9 @@ const __O = {
12
12
  };
13
13
  const CLS_REMOVE_BTN = "self-start text-zinc-400 dark:text-zinc-400 transition hover:text-red-500";
14
14
  export function CartItemRow({ item, onQtyChange, onRemove, href, isOutOfStock = false }) {
15
- return (_jsxs(Div, { surface: "card", padding: "sm", className: `flex gap-4 transition-opacity ${isOutOfStock ? "opacity-60" : ""}`, children: [_jsx(Div, { className: `h-20 w-20 flex-shrink-0 ${__O.hidden} rounded-lg bg-neutral-100 dark:bg-slate-800`, children: item.meta.image && (_jsx(Div, { role: "img", "aria-label": item.meta.title, className: "h-full w-full bg-center bg-cover", style: { backgroundImage: `url(${item.meta.image})` } })) }), _jsxs(Div, { className: "flex flex-1 flex-col justify-between", children: [_jsxs(Div, { className: "flex items-start gap-1.5", children: [href ? (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: `font-medium text-neutral-900 dark:text-zinc-100 hover:underline underline-offset-2 ${THEME_CONSTANTS.utilities.textClamp2}`, children: item.meta.title })) : (_jsx(Text, { className: `font-medium text-neutral-900 dark:text-zinc-100 ${THEME_CONSTANTS.utilities.textClamp2}`, children: item.meta.title })), isOutOfStock && (_jsx(Span, { weight: "semibold", className: "flex-shrink-0 rounded bg-error-surface px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-error", children: "Out of Stock" }))] }), item.meta.attributes &&
15
+ return (_jsxs(Div, { surface: "card", padding: "sm", className: `flex gap-4 transition-opacity ${isOutOfStock ? "opacity-60" : ""}`, children: [_jsx(Div, { className: `h-20 w-20 flex-shrink-0 ${__O.hidden} rounded-lg bg-neutral-100 dark:bg-slate-800`, children: item.meta.image && (_jsx(Div, { role: "img", "aria-label": item.meta.title, className: "h-full w-full bg-center bg-cover",
16
+ // audit-inline-style-ok: dynamic image URL
17
+ style: { backgroundImage: `url(${item.meta.image})` } })) }), _jsxs(Div, { className: "flex flex-1 flex-col justify-between", children: [_jsxs(Div, { className: "flex items-start gap-1.5", children: [href ? (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: `font-medium text-neutral-900 dark:text-zinc-100 hover:underline underline-offset-2 ${THEME_CONSTANTS.utilities.textClamp2}`, children: item.meta.title })) : (_jsx(Text, { className: `font-medium text-neutral-900 dark:text-zinc-100 ${THEME_CONSTANTS.utilities.textClamp2}`, children: item.meta.title })), isOutOfStock && (_jsx(Span, { weight: "semibold", className: "flex-shrink-0 rounded bg-error-surface px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-error", children: "Out of Stock" }))] }), item.meta.attributes &&
16
18
  Object.keys(item.meta.attributes).length > 0 && (_jsx(Text, { className: "text-xs text-neutral-500 dark:text-zinc-400", children: Object.entries(item.meta.attributes)
17
19
  .map(([k, v]) => `${k}: ${v}`)
18
20
  .join(", ") })), _jsxs(Row, { justify: "between", children: [_jsx(Text, { className: "font-semibold text-neutral-900 dark:text-zinc-100", children: formatCurrency(item.meta.price * item.quantity, item.meta.currency) }), onQtyChange && !isOutOfStock && (_jsxs(Row, { className: "gap-2", children: [_jsx(Button, { onClick: () => onQtyChange(item.id, item.quantity - 1), disabled: item.quantity <= 1, variant: "outline", size: "sm", className: "flex h-7 w-7 items-center justify-center rounded-full border border-neutral-200 dark:border-slate-600 text-sm disabled:opacity-40", children: "\u2212" }), _jsx(Span, { size: "sm", className: "min-w-[1.5rem] text-center", children: item.quantity }), _jsx(Button, { onClick: () => onQtyChange(item.id, item.quantity + 1), variant: "outline", size: "sm", className: "flex h-7 w-7 items-center justify-center rounded-full border border-neutral-200 dark:border-slate-600 text-sm", children: "+" })] })), isOutOfStock && (_jsxs(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400", children: ["Qty: ", item.quantity] }))] })] }), onRemove && (_jsx(Button, { onClick: () => onRemove(item.id), variant: "ghost", size: "sm", "aria-label": ACTIONS.CART["remove-item"].ariaLabel, className: CLS_REMOVE_BTN, children: "\u2715" }))] }));
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { DatabaseError, NotFoundError, ValidationError } from "../../../errors";
3
+ import { CART_FIELDS } from "../../../constants/field-names";
3
4
  const ERR_CART_ITEM_NOT_FOUND = "Cart item not found";
4
5
  const ERR_CART_ITEM_LOCKED = "This item requires payment and cannot be removed or modified.";
5
6
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
@@ -277,7 +278,7 @@ export class CartRepository extends BaseRepository {
277
278
  cutoff.setDate(cutoff.getDate() - ttlDays);
278
279
  const snap = await this.db
279
280
  .collection(this.collection)
280
- .where("updatedAt", "<", cutoff)
281
+ .where(CART_FIELDS.UPDATED_AT, "<", cutoff)
281
282
  .limit(500)
282
283
  .get();
283
284
  return snap.docs.map((d) => d.ref);
@@ -86,5 +86,9 @@ export async function BrandDetailPageView({ slug, initialBrand }) {
86
86
  counts.preOrders +
87
87
  counts.prizeDraws +
88
88
  counts.bundles;
89
- return (_jsxs(Main, { children: [_jsxs(Section, { className: `relative ${__O.hidden} ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-zinc-50 dark:bg-zinc-900"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 bg-center bg-cover", style: { backgroundImage: `url(${coverImage})` } }), _jsx(Div, { className: "absolute inset-0 bg-black/55" })] })), !hasCover && (_jsx("div", { className: "absolute inset-0 opacity-10", style: { backgroundColor: brandColor } })), _jsxs(Div, { className: `relative z-10 max-w-7xl mx-auto px-4 ${hasCover ? "py-12" : "py-8"}`, children: [_jsxs(Nav, { className: "flex items-center gap-1.5 text-sm mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.BRANDS ?? "/brands"), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Brands" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Span, { weight: "medium", className: hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-100", children: brand?.name ?? slug })] }), _jsxs(Div, { className: "flex items-center gap-4 mb-3", children: [brand?.display?.icon && (_jsx(Span, { className: "text-5xl leading-none", children: brand.display.icon })), _jsxs(_Fragment, { children: [_jsx(Heading, { level: 1, className: `text-3xl md:text-4xl font-bold ${hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-50"}`, children: brand?.name ?? slug }), brand?.description && typeof brand.description === "string" && !brand.description.startsWith("{") && (_jsx(Text, { className: `text-base max-w-2xl mt-1 ${hasCover ? "text-white/80" : "text-zinc-600 dark:text-zinc-400"}`, children: brand.description }))] })] }), _jsxs(Div, { className: "flex flex-wrap gap-2 mt-3", children: [counts.products > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400"}`, children: [counts.products.toLocaleString(), " ", counts.products === 1 ? "product" : "products"] })), counts.auctions > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"}`, children: [counts.auctions.toLocaleString(), " ", counts.auctions === 1 ? "auction" : "auctions"] })), counts.preOrders > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400"}`, children: [counts.preOrders.toLocaleString(), " ", counts.preOrders === 1 ? "pre-order" : "pre-orders"] })), totalItems === 0 && (_jsx(Span, { size: "sm", className: hasCover ? "text-white/60" : "text-zinc-400", children: "No items listed yet" }))] })] })] }), _jsx(Section, { className: "py-6", children: _jsx(Container, { size: "xl", children: brandName ? (_jsx(BrandDetailTabs, { brandName: brandName, initialProductsData: productsResult ?? undefined, initialBundles: brandBundles, counts: counts })) : (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "Brand not found." })) }) })] }));
89
+ return (_jsxs(Main, { children: [_jsxs(Section, { className: `relative ${__O.hidden} ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-zinc-50 dark:bg-zinc-900"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 bg-center bg-cover",
90
+ // audit-inline-style-ok: dynamic image URL
91
+ style: { backgroundImage: `url(${coverImage})` } }), _jsx(Div, { className: "absolute inset-0 bg-black/55" })] })), !hasCover && (_jsx("div", { className: "absolute inset-0 opacity-10",
92
+ // audit-inline-style-ok: runtime theme color
93
+ style: { backgroundColor: brandColor } })), _jsxs(Div, { className: `relative z-10 max-w-7xl mx-auto px-4 ${hasCover ? "py-12" : "py-8"}`, children: [_jsxs(Nav, { className: "flex items-center gap-1.5 text-sm mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.BRANDS ?? "/brands"), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Brands" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Span, { weight: "medium", className: hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-100", children: brand?.name ?? slug })] }), _jsxs(Div, { className: "flex items-center gap-4 mb-3", children: [brand?.display?.icon && (_jsx(Span, { className: "text-5xl leading-none", children: brand.display.icon })), _jsxs(_Fragment, { children: [_jsx(Heading, { level: 1, className: `text-3xl md:text-4xl font-bold ${hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-50"}`, children: brand?.name ?? slug }), brand?.description && typeof brand.description === "string" && !brand.description.startsWith("{") && (_jsx(Text, { className: `text-base max-w-2xl mt-1 ${hasCover ? "text-white/80" : "text-zinc-600 dark:text-zinc-400"}`, children: brand.description }))] })] }), _jsxs(Div, { className: "flex flex-wrap gap-2 mt-3", children: [counts.products > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400"}`, children: [counts.products.toLocaleString(), " ", counts.products === 1 ? "product" : "products"] })), counts.auctions > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"}`, children: [counts.auctions.toLocaleString(), " ", counts.auctions === 1 ? "auction" : "auctions"] })), counts.preOrders > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400"}`, children: [counts.preOrders.toLocaleString(), " ", counts.preOrders === 1 ? "pre-order" : "pre-orders"] })), totalItems === 0 && (_jsx(Span, { size: "sm", className: hasCover ? "text-white/60" : "text-zinc-400", children: "No items listed yet" }))] })] })] }), _jsx(Section, { className: "py-6", children: _jsx(Container, { size: "xl", children: brandName ? (_jsx(BrandDetailTabs, { brandName: brandName, initialProductsData: productsResult ?? undefined, initialBundles: brandBundles, counts: counts })) : (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "Brand not found." })) }) })] }));
90
94
  }
@@ -112,7 +112,9 @@ export async function CategoryDetailPageView({ slug }) {
112
112
  const totalCount = productCount + auctionCount + preOrderCount + prizeDrawCount + bundleCount + storeCount;
113
113
  const coverImage = category?.display?.coverImage;
114
114
  const hasCover = Boolean(coverImage);
115
- return (_jsxs(Main, { children: [_jsxs(Section, { className: `relative ${__O.hidden} ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-zinc-50 dark:bg-zinc-900"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 bg-center bg-cover", style: { backgroundImage: `url(${coverImage})` } }), _jsx(Div, { className: "absolute inset-0 bg-black/55" })] })), _jsxs(Div, { className: `relative z-10 max-w-7xl mx-auto px-4 ${hasCover ? "py-12" : "py-8"}`, children: [_jsxs(Nav, { className: "flex items-center gap-1.5 text-sm mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORIES), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Categories" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Span, { weight: "medium", className: hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-100", children: category?.name ?? slug })] }), _jsx(Heading, { level: 1, className: `text-3xl md:text-4xl font-bold mb-2 ${hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-50"}`, children: category?.name ?? slug }), category?.description && typeof category.description === "string" && !category.description.startsWith("{") && (_jsx(Text, { className: `text-base max-w-2xl mb-4 ${hasCover ? "text-white/80" : "text-zinc-600 dark:text-zinc-400"}`, children: category.description })), _jsxs(Div, { className: "flex flex-wrap gap-2", children: [productCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400"}`, children: [productCount.toLocaleString(), " ", productCount === 1 ? "product" : "products"] })), auctionCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"}`, children: [auctionCount.toLocaleString(), " ", auctionCount === 1 ? "auction" : "auctions"] })), preOrderCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400"}`, children: [preOrderCount.toLocaleString(), " ", preOrderCount === 1 ? "pre-order" : "pre-orders"] })), storeCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"}`, children: [storeCount.toLocaleString(), " ", storeCount === 1 ? "store" : "stores"] }))] })] })] }), childCategories.length > 0 && (_jsx(Section, { surface: "default", className: "border-b border-zinc-100 dark:border-zinc-800", children: _jsx(Div, { className: "max-w-7xl mx-auto px-4 py-3", children: _jsx(Div, { className: `flex gap-2.5 ${__O.xAuto} pb-1`, style: { scrollbarWidth: "none" }, children: childCategories.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)), className: "flex-shrink-0 flex items-center gap-1.5 rounded-full border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 px-4 py-1.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:border-primary hover:text-primary transition-colors whitespace-nowrap", children: [child.display?.icon && (_jsx(Span, { className: "leading-none", children: child.display.icon })), child.name, (child.metrics?.productCount ?? 0) > 0 && (_jsx(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400", children: (child.metrics?.productCount ?? 0).toLocaleString() }))] }, child.id))) }) }) })), _jsx(Section, { className: "py-6", children: _jsx(Container, { size: "xl", children: _jsx(CategoryDetailTabs, { categorySlug: slug, categoryId: category?.id, initialProductsData: productsResult ?? undefined, initialBundles: bundlesResult ?? [], initialStores: categoryStores, counts: {
115
+ return (_jsxs(Main, { children: [_jsxs(Section, { className: `relative ${__O.hidden} ${hasCover ? "min-h-[220px] md:min-h-[280px]" : "bg-zinc-50 dark:bg-zinc-900"}`, children: [hasCover && (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 bg-center bg-cover",
116
+ // audit-inline-style-ok: dynamic image URL
117
+ style: { backgroundImage: `url(${coverImage})` } }), _jsx(Div, { className: "absolute inset-0 bg-black/55" })] })), _jsxs(Div, { className: `relative z-10 max-w-7xl mx-auto px-4 ${hasCover ? "py-12" : "py-8"}`, children: [_jsxs(Nav, { className: "flex items-center gap-1.5 text-sm mb-4", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORIES), className: hasCover ? "text-white/70 hover:text-white transition-colors" : "text-zinc-500 dark:text-zinc-400 hover:text-primary-600 transition-colors", children: "Categories" }), _jsx(Span, { className: hasCover ? "text-white/40" : "text-zinc-400", children: "/" }), _jsx(Span, { weight: "medium", className: hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-100", children: category?.name ?? slug })] }), _jsx(Heading, { level: 1, className: `text-3xl md:text-4xl font-bold mb-2 ${hasCover ? "text-white" : "text-zinc-900 dark:text-zinc-50"}`, children: category?.name ?? slug }), category?.description && typeof category.description === "string" && !category.description.startsWith("{") && (_jsx(Text, { className: `text-base max-w-2xl mb-4 ${hasCover ? "text-white/80" : "text-zinc-600 dark:text-zinc-400"}`, children: category.description })), _jsxs(Div, { className: "flex flex-wrap gap-2", children: [productCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-primary/10 text-primary-700 dark:text-primary-400"}`, children: [productCount.toLocaleString(), " ", productCount === 1 ? "product" : "products"] })), auctionCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"}`, children: [auctionCount.toLocaleString(), " ", auctionCount === 1 ? "auction" : "auctions"] })), preOrderCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-400"}`, children: [preOrderCount.toLocaleString(), " ", preOrderCount === 1 ? "pre-order" : "pre-orders"] })), storeCount > 0 && (_jsxs(Span, { size: "xs", weight: "medium", className: `inline-flex items-center gap-1 px-2.5 py-1 rounded-full ${hasCover ? "bg-white/20 text-white backdrop-blur-sm" : "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"}`, children: [storeCount.toLocaleString(), " ", storeCount === 1 ? "store" : "stores"] }))] })] })] }), childCategories.length > 0 && (_jsx(Section, { surface: "default", className: "border-b border-zinc-100 dark:border-zinc-800", children: _jsxs(Div, { className: "max-w-7xl mx-auto px-4 py-3", children: ["// audit-inline-style-ok: dynamic CSS", _jsx(Div, { className: `flex gap-2.5 ${__O.xAuto} pb-1`, style: { scrollbarWidth: "none" }, children: childCategories.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)), className: "flex-shrink-0 flex items-center gap-1.5 rounded-full border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 px-4 py-1.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:border-primary hover:text-primary transition-colors whitespace-nowrap", children: [child.display?.icon && (_jsx(Span, { className: "leading-none", children: child.display.icon })), child.name, (child.metrics?.productCount ?? 0) > 0 && (_jsx(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400", children: (child.metrics?.productCount ?? 0).toLocaleString() }))] }, child.id))) })] }) })), _jsx(Section, { className: "py-6", children: _jsx(Container, { size: "xl", children: _jsx(CategoryDetailTabs, { categorySlug: slug, categoryId: category?.id, initialProductsData: productsResult ?? undefined, initialBundles: bundlesResult ?? [], initialStores: categoryStores, counts: {
116
118
  products: productCount,
117
119
  auctions: auctionCount,
118
120
  preOrders: preOrderCount,
@@ -12,7 +12,11 @@ const __O = {
12
12
  const CLS_FEATURED_DOT = "absolute left-2 top-2 rounded-full bg-amber-400 p-1 leading-none";
13
13
  export function CategoryCard({ category, href, onClick, className = "", }) {
14
14
  const productCount = category.metrics?.productCount ?? category.productCount ?? 0;
15
- const inner = (_jsxs(Div, { className: "flex h-full flex-col", children: [_jsxs(Div, { className: `relative aspect-[4/3] w-full ${__O.hidden} bg-gradient-to-br from-neutral-100 to-neutral-200 dark:from-zinc-800 dark:to-zinc-700 flex-shrink-0`, children: [category.display?.coverImage ? (_jsx(Div, { role: "img", "aria-label": category.name, className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${category.display.coverImage})` } })) : category.display?.color ? (_jsx(Div, { className: "h-full w-full opacity-80", style: { backgroundColor: category.display.color } })) : null, category.display?.icon && (_jsx(Div, { className: "absolute inset-0 flex items-center justify-center text-4xl", children: category.display.icon })), category.isFeatured && (_jsx(Span, { size: "xs", className: CLS_FEATURED_DOT, children: "\u2605" }))] }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p3}.5`, children: [_jsx(Text, { className: `font-semibold text-sm leading-snug ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-900 dark:text-white`, children: category.name }), category.description && (_jsx(Text, { className: `mt-1 text-xs ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-500 dark:text-zinc-400 flex-1`, children: category.description })), _jsxs(Div, { className: "mt-2 flex items-center justify-between gap-2", children: [_jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: [productCount.toLocaleString(), " ", productCount === 1 ? "item" : "items"] }), _jsxs(Span, { size: "xs", weight: "medium", className: "inline-flex items-center gap-1 rounded-md border border-zinc-200 dark:border-zinc-700 px-2.5 py-1 text-zinc-600 dark:text-zinc-300 group-hover:bg-primary group-hover:border-primary group-hover:text-white transition-colors", children: ["Browse ", _jsx(ArrowRight, { className: "h-3 w-3" })] })] })] })] }));
15
+ const inner = (_jsxs(Div, { className: "flex h-full flex-col", children: [_jsxs(Div, { className: `relative aspect-[4/3] w-full ${__O.hidden} bg-gradient-to-br from-neutral-100 to-neutral-200 dark:from-zinc-800 dark:to-zinc-700 flex-shrink-0`, children: [category.display?.coverImage ? (_jsx(Div, { role: "img", "aria-label": category.name, className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105",
16
+ // audit-inline-style-ok: dynamic image URL
17
+ style: { backgroundImage: `url(${category.display.coverImage})` } })) : category.display?.color ? (_jsx(Div, { className: "h-full w-full opacity-80",
18
+ // audit-inline-style-ok: runtime theme color
19
+ style: { backgroundColor: category.display.color } })) : null, category.display?.icon && (_jsx(Div, { className: "absolute inset-0 flex items-center justify-center text-4xl", children: category.display.icon })), category.isFeatured && (_jsx(Span, { size: "xs", className: CLS_FEATURED_DOT, children: "\u2605" }))] }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p3}.5`, children: [_jsx(Text, { className: `font-semibold text-sm leading-snug ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-900 dark:text-white`, children: category.name }), category.description && (_jsx(Text, { className: `mt-1 text-xs ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-500 dark:text-zinc-400 flex-1`, children: category.description })), _jsxs(Div, { className: "mt-2 flex items-center justify-between gap-2", children: [_jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400", children: [productCount.toLocaleString(), " ", productCount === 1 ? "item" : "items"] }), _jsxs(Span, { size: "xs", weight: "medium", className: "inline-flex items-center gap-1 rounded-md border border-zinc-200 dark:border-zinc-700 px-2.5 py-1 text-zinc-600 dark:text-zinc-300 group-hover:bg-primary group-hover:border-primary group-hover:text-white transition-colors", children: ["Browse ", _jsx(ArrowRight, { className: "h-3 w-3" })] })] })] })] }));
16
20
  const cardClass = `group relative flex flex-col overflow-hidden rounded-xl border border-neutral-200 bg-white dark:border-zinc-700 dark:bg-zinc-900 shadow-sm transition hover:shadow-md h-full ${className}`;
17
21
  if (href) {
18
22
  return (_jsx(Link, { href: href, className: cardClass, children: inner }));
@@ -22,13 +22,17 @@ export function getCategoryTableColumns(onEdit, onDelete, labels = {}) {
22
22
  {
23
23
  key: "image",
24
24
  header: "",
25
- render: (cat) => (_jsx(Div, { className: `relative w-9 h-9 rounded ${__O.hidden} flex-shrink-0`, children: cat.display?.coverImage ? (_jsx(MediaImage, { src: cat.display.coverImage, alt: "", size: "thumbnail", className: "w-full h-full object-cover" })) : (_jsx(Div, { className: "w-full h-full flex items-center justify-center text-base", style: { backgroundColor: cat.display?.color ?? "#94a3b8", color: "#fff" }, children: cat.display?.icon ?? "🗂️" })) })),
25
+ render: (cat) => (_jsx(Div, { className: `relative w-9 h-9 rounded ${__O.hidden} flex-shrink-0`, children: cat.display?.coverImage ? (_jsx(MediaImage, { src: cat.display.coverImage, alt: "", size: "thumbnail", className: "w-full h-full object-cover" })) : (_jsx(Div, { className: "w-full h-full flex items-center justify-center text-base",
26
+ // audit-inline-style-ok: runtime theme color
27
+ style: { backgroundColor: cat.display?.color ?? "#94a3b8", color: "#fff" }, children: cat.display?.icon ?? "🗂️" })) })),
26
28
  },
27
29
  {
28
30
  key: "name",
29
31
  header: L.colName,
30
32
  sortable: true,
31
- render: (cat) => (_jsxs(Div, { style: { paddingLeft: `${cat.tier * 20}px` }, children: [cat.name, cat.tier > 0 && (_jsxs(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400 ml-2", children: ["(Tier ", cat.tier, ")"] }))] })),
33
+ render: (cat) => (
34
+ // audit-inline-style-ok: computed pixel offset
35
+ _jsxs(Div, { style: { paddingLeft: `${cat.tier * 20}px` }, children: [cat.name, cat.tier > 0 && (_jsxs(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400 ml-2", children: ["(Tier ", cat.tier, ")"] }))] })),
32
36
  },
33
37
  {
34
38
  key: "slug",
@@ -19,7 +19,9 @@ function CategoryTreeNode({ item, children = [], activeId, onSelect, depth = 0,
19
19
  setExpanded((p) => !p);
20
20
  onSelect?.(item);
21
21
  }, className: `flex cursor-pointer items-center gap-1 rounded-md px-2 py-1.5 text-sm transition select-none
22
- ${isActive ? "bg-primary-50 font-semibold text-primary-700 dark:bg-primary-900/30 dark:text-primary-400" : "text-neutral-700 hover:bg-neutral-50 dark:text-zinc-300 dark:hover:bg-zinc-800"}`, style: { paddingLeft: `${8 + indent}px` }, children: [hasChildren && (_jsx(Span, { size: "xs", "aria-hidden": "true", className: `text-zinc-400 dark:text-zinc-400 transition-transform duration-150 ${expanded ? "rotate-90" : ""}`, children: "\u25B6" })), !hasChildren && _jsx(Span, { className: "w-3" }), item.display?.icon && (_jsx(Span, { size: "base", "aria-hidden": "true", className: "flex-shrink-0", children: item.display.icon })), _jsx(Text, { className: "flex-1 truncate", children: item.name }), item.metrics && (_jsx(Span, { size: "xs", className: "ml-auto flex-shrink-0 text-zinc-400 dark:text-zinc-400 tabular-nums", children: item.metrics.productCount }))] }), hasChildren && expanded && (_jsx(Div, { role: "group", children: children.map((child) => (_jsx(CategoryTreeNode, { item: child, activeId: activeId, onSelect: onSelect, depth: depth + 1 }, child.id))) }))] }));
22
+ ${isActive ? "bg-primary-50 font-semibold text-primary-700 dark:bg-primary-900/30 dark:text-primary-400" : "text-neutral-700 hover:bg-neutral-50 dark:text-zinc-300 dark:hover:bg-zinc-800"}`,
23
+ // audit-inline-style-ok: computed pixel offset
24
+ style: { paddingLeft: `${8 + indent}px` }, children: [hasChildren && (_jsx(Span, { size: "xs", "aria-hidden": "true", className: `text-zinc-400 dark:text-zinc-400 transition-transform duration-150 ${expanded ? "rotate-90" : ""}`, children: "\u25B6" })), !hasChildren && _jsx(Span, { className: "w-3" }), item.display?.icon && (_jsx(Span, { size: "base", "aria-hidden": "true", className: "flex-shrink-0", children: item.display.icon })), _jsx(Text, { className: "flex-1 truncate", children: item.name }), item.metrics && (_jsx(Span, { size: "xs", className: "ml-auto flex-shrink-0 text-zinc-400 dark:text-zinc-400 tabular-nums", children: item.metrics.productCount }))] }), hasChildren && expanded && (_jsx(Div, { role: "group", children: children.map((child) => (_jsx(CategoryTreeNode, { item: child, activeId: activeId, onSelect: onSelect, depth: depth + 1 }, child.id))) }))] }));
23
25
  }
24
26
  /**
25
27
  * CategoryTree — hierarchical expandable navigation for categories.
@@ -2,5 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button, Div, Heading, Text } from "../../../ui";
3
3
  import { THEME_CONSTANTS } from "../../../tokens";
4
4
  export function ConcernCard({ concern, onClick, className = "", }) {
5
- return (_jsxs(Button, { type: "button", variant: "outline", onClick: () => onClick?.(concern), className: `group flex flex-col items-center gap-3 rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 text-center shadow-sm transition hover:border-primary dark:hover:border-primary-400 hover:shadow-md ${className}`, children: [concern.display?.coverImage && (_jsx(Div, { role: "img", "aria-label": concern.name, className: "h-16 w-16 rounded-full bg-center bg-cover", style: { backgroundImage: `url(${concern.display.coverImage})` } })), _jsxs(Div, { children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold text-neutral-900 dark:text-zinc-100 group-hover:text-primary dark:group-hover:text-primary-400", children: concern.name }), concern.description && (_jsx(Text, { className: `mt-1 text-xs ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-500 dark:text-zinc-400`, children: concern.description }))] })] }));
5
+ return (_jsxs(Button, { type: "button", variant: "outline", onClick: () => onClick?.(concern), className: `group flex flex-col items-center gap-3 rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 text-center shadow-sm transition hover:border-primary dark:hover:border-primary-400 hover:shadow-md ${className}`, children: [concern.display?.coverImage && (_jsx(Div, { role: "img", "aria-label": concern.name, className: "h-16 w-16 rounded-full bg-center bg-cover",
6
+ // audit-inline-style-ok: dynamic image URL
7
+ style: { backgroundImage: `url(${concern.display.coverImage})` } })), _jsxs(Div, { children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold text-neutral-900 dark:text-zinc-100 group-hover:text-primary dark:group-hover:text-primary-400", children: concern.name }), concern.description && (_jsx(Text, { className: `mt-1 text-xs ${THEME_CONSTANTS.utilities.textClamp2} text-neutral-500 dark:text-zinc-400`, children: concern.description }))] })] }));
6
8
  }