@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
@@ -1,6 +1,7 @@
1
1
  import { increment, arrayUnion, arrayRemove, } from "../../../contracts/field-ops";
2
2
  import { DatabaseError } from "../../../errors";
3
3
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
4
+ import { PRODUCT_FIELDS } from "../../../constants/field-names";
4
5
  import { CATEGORY_FIELDS, CATEGORIES_COLLECTION, MIN_ITEMS_FOR_FEATURED, buildCategoryTree, calculateCategoryFields, canBeFeatured, createCategoryId, isValidCategoryMove, } from "../schemas";
5
6
  export class CategoriesRepository extends BaseRepository {
6
7
  constructor() {
@@ -80,9 +81,9 @@ export class CategoriesRepository extends BaseRepository {
80
81
  try {
81
82
  const snapshot = await this.db
82
83
  .collection(this.collection)
83
- .where("tier", "==", 0)
84
- .where("isActive", "==", true)
85
- .orderBy("order", "asc")
84
+ .where(CATEGORY_FIELDS.TIER, "==", 0)
85
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
86
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
86
87
  .get();
87
88
  return snapshot.docs
88
89
  .map((doc) => this.mapDoc(doc))
@@ -96,8 +97,8 @@ export class CategoriesRepository extends BaseRepository {
96
97
  try {
97
98
  const snapshot = await this.db
98
99
  .collection(this.collection)
99
- .where("isLeaf", "==", true)
100
- .where("isActive", "==", true)
100
+ .where(CATEGORY_FIELDS.IS_LEAF, "==", true)
101
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
101
102
  .limit(500)
102
103
  .get();
103
104
  return snapshot.docs.map((doc) => this.mapDoc(doc));
@@ -110,9 +111,9 @@ export class CategoriesRepository extends BaseRepository {
110
111
  try {
111
112
  const snapshot = await this.db
112
113
  .collection(this.collection)
113
- .where("tier", "==", tier)
114
- .where("isActive", "==", true)
115
- .orderBy("order", "asc")
114
+ .where(CATEGORY_FIELDS.TIER, "==", tier)
115
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
116
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
116
117
  .get();
117
118
  return snapshot.docs
118
119
  .map((doc) => this.mapDoc(doc))
@@ -126,9 +127,9 @@ export class CategoriesRepository extends BaseRepository {
126
127
  try {
127
128
  const snapshot = await this.db
128
129
  .collection(this.collection)
129
- .where("rootId", "==", rootId)
130
- .orderBy("tier", "asc")
131
- .orderBy("order", "asc")
130
+ .where(CATEGORY_FIELDS.ROOT_ID, "==", rootId)
131
+ .orderBy(CATEGORY_FIELDS.TIER, "asc")
132
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
132
133
  .get();
133
134
  return snapshot.docs.map((doc) => this.mapDoc(doc));
134
135
  }
@@ -141,7 +142,7 @@ export class CategoriesRepository extends BaseRepository {
141
142
  const snapshot = await this.db
142
143
  .collection(this.collection)
143
144
  .where("parentIds", "array-contains", parentId)
144
- .orderBy("order", "asc")
145
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
145
146
  .limit(100)
146
147
  .get();
147
148
  return snapshot.docs
@@ -156,8 +157,8 @@ export class CategoriesRepository extends BaseRepository {
156
157
  try {
157
158
  const snapshot = await this.db
158
159
  .collection(this.collection)
159
- .where("isFeatured", "==", true)
160
- .where("isActive", "==", true)
160
+ .where(CATEGORY_FIELDS.IS_FEATURED, "==", true)
161
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
161
162
  .orderBy("featuredPriority", "asc")
162
163
  .get();
163
164
  return snapshot.docs
@@ -173,8 +174,8 @@ export class CategoriesRepository extends BaseRepository {
173
174
  const snapshot = await this.db
174
175
  .collection(this.collection)
175
176
  .where("isBrand", "==", true)
176
- .where("isActive", "==", true)
177
- .orderBy("order", "asc")
177
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
178
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
178
179
  .get();
179
180
  const brands = snapshot.docs.map((doc) => this.mapDoc(doc));
180
181
  return limit > 0 ? brands.slice(0, limit) : brands;
@@ -368,9 +369,9 @@ export class CategoriesRepository extends BaseRepository {
368
369
  async listByType(type, opts = {}) {
369
370
  let q = this.db
370
371
  .collection(this.collection)
371
- .where("categoryType", "==", type);
372
+ .where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", type);
372
373
  if (opts.activeOnly)
373
- q = q.where("isActive", "==", true);
374
+ q = q.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true);
374
375
  if (opts.limit)
375
376
  q = q.limit(opts.limit);
376
377
  const snap = await q.get();
@@ -380,10 +381,10 @@ export class CategoriesRepository extends BaseRepository {
380
381
  async findBySlugAndType(slug, type) {
381
382
  let q = this.db
382
383
  .collection(this.collection)
383
- .where("slug", "==", slug)
384
+ .where(CATEGORY_FIELDS.SLUG, "==", slug)
384
385
  .limit(1);
385
386
  if (type)
386
- q = q.where("categoryType", "==", type);
387
+ q = q.where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", type);
387
388
  const snap = await q.get();
388
389
  if (snap.empty)
389
390
  return null;
@@ -398,8 +399,8 @@ export class CategoriesRepository extends BaseRepository {
398
399
  const snap = await this.db
399
400
  .collection("products")
400
401
  .where("sublistingCategoryId", "==", sublistingId)
401
- .where("status", "==", "published")
402
- .orderBy("price", "asc")
402
+ .where(PRODUCT_FIELDS.STATUS, "==", "published")
403
+ .orderBy(PRODUCT_FIELDS.PRICE, "asc")
403
404
  .limit(limit)
404
405
  .get();
405
406
  return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
@@ -428,9 +429,9 @@ export class CategoriesRepository extends BaseRepository {
428
429
  async findActiveBrands() {
429
430
  const snap = await this.db
430
431
  .collection(this.collection)
431
- .where("categoryType", "==", "brand")
432
- .where("isActive", "==", true)
433
- .orderBy("order", "asc")
432
+ .where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", "brand")
433
+ .where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
434
+ .orderBy(CATEGORY_FIELDS.ORDER, "asc")
434
435
  .get();
435
436
  return snap.docs.map((d) => this.mapDoc(d));
436
437
  }
@@ -244,6 +244,7 @@ export declare const CATEGORY_FIELDS: {
244
244
  readonly DISPLAY: "display";
245
245
  readonly IS_ACTIVE: "isActive";
246
246
  readonly IS_SEARCHABLE: "isSearchable";
247
+ readonly CATEGORY_TYPE: "categoryType";
247
248
  readonly CREATED_BY: "createdBy";
248
249
  readonly CREATED_AT: "createdAt";
249
250
  readonly UPDATED_AT: "updatedAt";
@@ -178,6 +178,7 @@ export const CATEGORY_FIELDS = {
178
178
  DISPLAY: "display",
179
179
  IS_ACTIVE: "isActive",
180
180
  IS_SEARCHABLE: "isSearchable",
181
+ CATEGORY_TYPE: "categoryType",
181
182
  CREATED_BY: "createdBy",
182
183
  CREATED_AT: "createdAt",
183
184
  UPDATED_AT: "updatedAt",
@@ -23,12 +23,12 @@ export declare const categoryDisplaySchema: z.ZodObject<{
23
23
  showInMenu: z.ZodOptional<z.ZodBoolean>;
24
24
  }, "strip", z.ZodTypeAny, {
25
25
  icon?: string | undefined;
26
- showInMenu?: boolean | undefined;
27
26
  coverImage?: string | undefined;
27
+ showInMenu?: boolean | undefined;
28
28
  }, {
29
29
  icon?: string | undefined;
30
- showInMenu?: boolean | undefined;
31
30
  coverImage?: string | undefined;
31
+ showInMenu?: boolean | undefined;
32
32
  }>;
33
33
  export declare const categoryMetricsSchema: z.ZodObject<{
34
34
  productCount: z.ZodNumber;
@@ -104,12 +104,12 @@ export declare const categoryItemSchema: z.ZodObject<{
104
104
  showInMenu: z.ZodOptional<z.ZodBoolean>;
105
105
  }, "strip", z.ZodTypeAny, {
106
106
  icon?: string | undefined;
107
- showInMenu?: boolean | undefined;
108
107
  coverImage?: string | undefined;
108
+ showInMenu?: boolean | undefined;
109
109
  }, {
110
110
  icon?: string | undefined;
111
- showInMenu?: boolean | undefined;
112
111
  coverImage?: string | undefined;
112
+ showInMenu?: boolean | undefined;
113
113
  }>>;
114
114
  createdAt: z.ZodOptional<z.ZodString>;
115
115
  updatedAt: z.ZodOptional<z.ZodString>;
@@ -125,8 +125,8 @@ export declare const categoryItemSchema: z.ZodObject<{
125
125
  updatedAt?: string | undefined;
126
126
  display?: {
127
127
  icon?: string | undefined;
128
- showInMenu?: boolean | undefined;
129
128
  coverImage?: string | undefined;
129
+ showInMenu?: boolean | undefined;
130
130
  } | undefined;
131
131
  order?: number | undefined;
132
132
  isFeatured?: boolean | undefined;
@@ -137,8 +137,8 @@ export declare const categoryItemSchema: z.ZodObject<{
137
137
  ogImage?: string | undefined;
138
138
  } | undefined;
139
139
  rootId?: string | undefined;
140
- parentIds?: string[] | undefined;
141
140
  isLeaf?: boolean | undefined;
141
+ parentIds?: string[] | undefined;
142
142
  featuredPriority?: number | undefined;
143
143
  childrenIds?: string[] | undefined;
144
144
  metrics?: {
@@ -158,8 +158,8 @@ export declare const categoryItemSchema: z.ZodObject<{
158
158
  updatedAt?: string | undefined;
159
159
  display?: {
160
160
  icon?: string | undefined;
161
- showInMenu?: boolean | undefined;
162
161
  coverImage?: string | undefined;
162
+ showInMenu?: boolean | undefined;
163
163
  } | undefined;
164
164
  order?: number | undefined;
165
165
  isFeatured?: boolean | undefined;
@@ -170,8 +170,8 @@ export declare const categoryItemSchema: z.ZodObject<{
170
170
  ogImage?: string | undefined;
171
171
  } | undefined;
172
172
  rootId?: string | undefined;
173
- parentIds?: string[] | undefined;
174
173
  isLeaf?: boolean | undefined;
174
+ parentIds?: string[] | undefined;
175
175
  featuredPriority?: number | undefined;
176
176
  childrenIds?: string[] | undefined;
177
177
  metrics?: {
@@ -194,14 +194,14 @@ export declare const categoryListParamsSchema: z.ZodObject<{
194
194
  q?: string | undefined;
195
195
  page?: number | undefined;
196
196
  perPage?: number | undefined;
197
- tier?: number | undefined;
198
197
  parentId?: string | undefined;
198
+ tier?: number | undefined;
199
199
  }, {
200
200
  type?: "category" | "brand" | "collection" | "concern" | undefined;
201
201
  featured?: boolean | undefined;
202
202
  q?: string | undefined;
203
203
  page?: number | undefined;
204
204
  perPage?: number | undefined;
205
- tier?: number | undefined;
206
205
  parentId?: string | undefined;
206
+ tier?: number | undefined;
207
207
  }>;
@@ -3,7 +3,9 @@ import { Div, Heading, Text, TextLink } from "../../../ui";
3
3
  import { LAYOUT } from "../../../tokens";
4
4
  const CLS_PLACEHOLDER = "w-full bg-gradient-to-br from-indigo-100 to-purple-100 dark:from-indigo-900/30 dark:to-purple-900/30";
5
5
  export function CollectionCard({ collection, href }) {
6
- return (_jsxs(TextLink, { href: href, className: "group relative block overflow-hidden rounded-xl bg-gray-100 dark:bg-slate-800 transition-shadow hover:shadow-lg", children: [collection.image ? (_jsx(Div, { role: "img", "aria-label": collection.title, className: `${LAYOUT.cardHeight.md} w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105`, style: { backgroundImage: `url(${collection.image})` } })) : (_jsx(Div, { className: `${LAYOUT.cardHeight.md} ${CLS_PLACEHOLDER}` })), _jsxs(Div, { surface: "default", padding: "sm", children: [_jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100", children: collection.title }), collection.subtitle && (_jsx(Text, { className: "mt-1 text-sm text-gray-500 dark:text-zinc-400", children: collection.subtitle })), collection.productCount !== undefined && (_jsxs(Text, { className: "mt-2 text-xs text-gray-400 dark:text-zinc-500", children: [collection.productCount, " ", collection.productCount === 1 ? "item" : "items"] }))] })] }));
6
+ return (_jsxs(TextLink, { href: href, className: "group relative block overflow-hidden rounded-xl bg-gray-100 dark:bg-slate-800 transition-shadow hover:shadow-lg", children: [collection.image ? (_jsx(Div, { role: "img", "aria-label": collection.title, className: `${LAYOUT.cardHeight.md} w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105`,
7
+ // audit-inline-style-ok: dynamic image URL
8
+ style: { backgroundImage: `url(${collection.image})` } })) : (_jsx(Div, { className: `${LAYOUT.cardHeight.md} ${CLS_PLACEHOLDER}` })), _jsxs(Div, { surface: "default", padding: "sm", children: [_jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100", children: collection.title }), collection.subtitle && (_jsx(Text, { className: "mt-1 text-sm text-gray-500 dark:text-zinc-400", children: collection.subtitle })), collection.productCount !== undefined && (_jsxs(Text, { className: "mt-2 text-xs text-gray-400 dark:text-zinc-500", children: [collection.productCount, " ", collection.productCount === 1 ? "item" : "items"] }))] })] }));
7
9
  }
8
10
  export function CollectionGrid({ collections, getHref }) {
9
11
  return (_jsx(Div, { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: collections.map((c) => (_jsx(CollectionCard, { collection: c, href: getHref(c.slug) }, c.slug))) }));
@@ -31,6 +31,8 @@ export function EventCard({ event, labels = {}, onParticipate, className = "", s
31
31
  const msLeft = endsAt.getTime() - now.getTime();
32
32
  const daysLeft = Math.max(0, Math.ceil(msLeft / (1000 * 60 * 60 * 24)));
33
33
  const detailHref = String(ROUTES.PUBLIC.EVENT_DETAIL(event.slug ?? event.id));
34
- return (_jsxs(Article, { className: `group relative flex h-full ${LAYOUT.cardHeight.event} flex-col overflow-hidden rounded-xl border bg-white shadow-sm transition-shadow hover:shadow-md dark:bg-slate-900 ${isSelected ? "border-primary outline outline-2 outline-primary" : "border-zinc-200 dark:border-slate-700"} ${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(event.id, !isSelected); }, label: isSelected ? "Deselect event" : "Select event", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Link, { href: detailHref, className: "block flex-shrink-0", children: event.coverImageUrl ? (_jsx(Div, { className: `aspect-video ${__O.hidden}`, children: _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(${event.coverImageUrl})` } }) })) : (_jsx(Div, { className: "aspect-video bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-slate-800 dark:to-slate-700 flex items-center justify-center", children: _jsx(Span, { className: "text-5xl opacity-40", "aria-hidden": "true", children: TYPE_ICONS[event.type] }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 mb-2", children: [_jsx(Span, { size: "lg", "aria-hidden": "true", children: TYPE_ICONS[event.type] }), _jsx(EventStatusBadge, { status: event.status })] }), _jsx(Link, { href: detailHref, className: "block", children: _jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100 text-base leading-snug mb-1 group-hover:text-primary transition-colors", children: safeTitle }) }), _jsx(RichText, { html: normalizeRichTextHtml(event.description ?? ""), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: `mb-3 ${THEME_CONSTANTS.utilities.textClamp3} text-sm text-zinc-600 dark:text-zinc-400` }), _jsxs(Div, { className: "mb-3 mt-auto flex items-center justify-between text-xs text-zinc-500 dark:text-zinc-400", children: [event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE &&
34
+ return (_jsxs(Article, { className: `group relative flex h-full ${LAYOUT.cardHeight.event} flex-col overflow-hidden rounded-xl border bg-white shadow-sm transition-shadow hover:shadow-md dark:bg-slate-900 ${isSelected ? "border-primary outline outline-2 outline-primary" : "border-zinc-200 dark:border-slate-700"} ${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(event.id, !isSelected); }, label: isSelected ? "Deselect event" : "Select event", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Link, { href: detailHref, className: "block flex-shrink-0", children: event.coverImageUrl ? (_jsx(Div, { className: `aspect-video ${__O.hidden}`, children: _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(${event.coverImageUrl})` } }) })) : (_jsx(Div, { className: "aspect-video bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-slate-800 dark:to-slate-700 flex items-center justify-center", children: _jsx(Span, { className: "text-5xl opacity-40", "aria-hidden": "true", children: TYPE_ICONS[event.type] }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 mb-2", children: [_jsx(Span, { size: "lg", "aria-hidden": "true", children: TYPE_ICONS[event.type] }), _jsx(EventStatusBadge, { status: event.status })] }), _jsx(Link, { href: detailHref, className: "block", children: _jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100 text-base leading-snug mb-1 group-hover:text-primary transition-colors", children: safeTitle }) }), _jsx(RichText, { html: normalizeRichTextHtml(event.description ?? ""), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: `mb-3 ${THEME_CONSTANTS.utilities.textClamp3} text-sm text-zinc-600 dark:text-zinc-400` }), _jsxs(Div, { className: "mb-3 mt-auto flex items-center justify-between text-xs text-zinc-500 dark:text-zinc-400", children: [event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE &&
35
37
  daysLeft > 0 && _jsxs(Span, { children: ["\u23F1 ", daysLeft, "d remaining"] }), _jsxs(Span, { children: ["\uD83D\uDC65 ", event.stats.totalEntries, " ", labels.entries ?? "entries"] })] }), event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE && onParticipate ? (_jsx(Button, { type: "button", onClick: () => onParticipate(event), className: "w-full rounded-lg bg-primary py-2 text-sm font-medium text-white transition-colors hover:bg-primary-600", children: labels.participate ?? "Participate" })) : (_jsxs(TextLink, { href: detailHref, className: "inline-flex w-full items-center justify-center gap-1.5 rounded-lg border border-zinc-300 px-3 py-2 text-sm font-medium text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-slate-600 dark:text-zinc-200 dark:hover:bg-slate-800", children: [labels.viewDetails ?? "View details", " \u2192"] }))] })] }));
36
38
  }
@@ -1,10 +1,11 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Div } from "../../../ui";
3
+ import { Skeleton } from "../../../ui/components/Skeleton";
3
4
  export function EventParticipateView({ isLoading = false, isSubmitted = false, renderEventInfo, renderForm, renderAction, renderSuccess, renderSkeleton, renderAuthGate, className = "", }) {
4
5
  if (isLoading) {
5
6
  if (renderSkeleton)
6
7
  return _jsx(_Fragment, { children: renderSkeleton() });
7
- return _jsx(Div, { className: "flex justify-center py-20", children: "Loading\u2026" });
8
+ return (_jsxs(Div, { className: "max-w-xl mx-auto space-y-4 py-6", children: [_jsx(Skeleton, { variant: "rectangular", height: "32px" }), _jsx(Skeleton, { variant: "rectangular", height: "80px" }), _jsx(Skeleton, { variant: "rectangular", height: "48px" })] }));
8
9
  }
9
10
  if (renderAuthGate)
10
11
  return _jsx(_Fragment, { children: renderAuthGate() });
@@ -275,6 +275,8 @@ export declare const eventItemSchema: z.ZodObject<{
275
275
  approvedEntries: number;
276
276
  flaggedEntries: number;
277
277
  };
278
+ startsAt: string;
279
+ endsAt: string;
278
280
  createdBy: string;
279
281
  coverImage: {
280
282
  url: string;
@@ -287,8 +289,6 @@ export declare const eventItemSchema: z.ZodObject<{
287
289
  url: string;
288
290
  type: "image";
289
291
  } | null;
290
- startsAt: string;
291
- endsAt: string;
292
292
  additionalImages: {
293
293
  url: string;
294
294
  type: "image" | "video" | "file";
@@ -346,9 +346,9 @@ export declare const eventItemSchema: z.ZodObject<{
346
346
  approvedEntries: number;
347
347
  flaggedEntries: number;
348
348
  };
349
- createdBy: string;
350
349
  startsAt: string;
351
350
  endsAt: string;
351
+ createdBy: string;
352
352
  coverImage?: string | {
353
353
  url: string;
354
354
  type: "image" | "video" | "file";
@@ -31,12 +31,12 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
31
31
  priority: number;
32
32
  isActive: boolean;
33
33
  question: string;
34
- showInFooter: boolean;
35
34
  showOnHomepage: boolean;
36
35
  answer: {
37
36
  text: string;
38
37
  format: "html" | "plain" | "markdown";
39
38
  };
39
+ showInFooter: boolean;
40
40
  isPinned: boolean;
41
41
  useSiteSettings: boolean;
42
42
  tags?: string[] | undefined;
@@ -56,8 +56,8 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
56
56
  priority?: number | undefined;
57
57
  isActive?: boolean | undefined;
58
58
  variables?: Record<string, string> | undefined;
59
- showInFooter?: boolean | undefined;
60
59
  showOnHomepage?: boolean | undefined;
60
+ showInFooter?: boolean | undefined;
61
61
  isPinned?: boolean | undefined;
62
62
  relatedFAQs?: string[] | undefined;
63
63
  useSiteSettings?: boolean | undefined;
@@ -67,12 +67,12 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
67
67
  priority: number;
68
68
  isActive: boolean;
69
69
  question: string;
70
- showInFooter: boolean;
71
70
  showOnHomepage: boolean;
72
71
  answer: {
73
72
  text: string;
74
73
  format: "html" | "plain" | "markdown";
75
74
  };
75
+ showInFooter: boolean;
76
76
  isPinned: boolean;
77
77
  useSiteSettings: boolean;
78
78
  tags?: string[] | undefined;
@@ -92,8 +92,8 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
92
92
  priority?: number | undefined;
93
93
  isActive?: boolean | undefined;
94
94
  variables?: Record<string, string> | undefined;
95
- showInFooter?: boolean | undefined;
96
95
  showOnHomepage?: boolean | undefined;
96
+ showInFooter?: boolean | undefined;
97
97
  isPinned?: boolean | undefined;
98
98
  relatedFAQs?: string[] | undefined;
99
99
  useSiteSettings?: boolean | undefined;
@@ -131,12 +131,12 @@ export declare const faqUpdateSchema: z.ZodObject<{
131
131
  isActive?: boolean | undefined;
132
132
  variables?: Record<string, string> | undefined;
133
133
  question?: string | undefined;
134
- showInFooter?: boolean | undefined;
135
134
  showOnHomepage?: boolean | undefined;
136
135
  answer?: {
137
136
  text: string;
138
137
  format: "html" | "plain" | "markdown";
139
138
  } | undefined;
139
+ showInFooter?: boolean | undefined;
140
140
  isPinned?: boolean | undefined;
141
141
  relatedFAQs?: string[] | undefined;
142
142
  useSiteSettings?: boolean | undefined;
@@ -149,12 +149,12 @@ export declare const faqUpdateSchema: z.ZodObject<{
149
149
  isActive?: boolean | undefined;
150
150
  variables?: Record<string, string> | undefined;
151
151
  question?: string | undefined;
152
- showInFooter?: boolean | undefined;
153
152
  showOnHomepage?: boolean | undefined;
154
153
  answer?: {
155
154
  text: string;
156
155
  format?: "html" | "plain" | "markdown" | undefined;
157
156
  } | undefined;
157
+ showInFooter?: boolean | undefined;
158
158
  isPinned?: boolean | undefined;
159
159
  relatedFAQs?: string[] | undefined;
160
160
  useSiteSettings?: boolean | undefined;
@@ -1,6 +1,7 @@
1
1
  import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
2
2
  import { DatabaseError } from "../../../errors";
3
3
  import { increment } from "../../../contracts/field-ops";
4
+ import { FAQ_FIELDS } from "../../../constants/field-names";
4
5
  import { FAQS_COLLECTION, createFAQId, slugifyQuestion, } from "../schemas";
5
6
  export class FAQsRepository {
6
7
  constructor(repo) {
@@ -116,16 +117,16 @@ export class FirebaseFAQsRepository extends BaseRepository {
116
117
  throw new DatabaseError("Combining FAQ tag filters and token search requires a dedicated search index");
117
118
  }
118
119
  if (tags.length === 1) {
119
- baseQuery = baseQuery.where("tags", "array-contains", tags[0]);
120
+ baseQuery = baseQuery.where(FAQ_FIELDS.TAGS, "array-contains", tags[0]);
120
121
  }
121
122
  else if (tags.length > 1) {
122
- baseQuery = baseQuery.where("tags", "array-contains-any", tags.slice(0, 10));
123
+ baseQuery = baseQuery.where(FAQ_FIELDS.TAGS, "array-contains-any", tags.slice(0, 10));
123
124
  }
124
125
  if (searchTokens.length === 1) {
125
- baseQuery = baseQuery.where("searchTokens", "array-contains", searchTokens[0]);
126
+ baseQuery = baseQuery.where(FAQ_FIELDS.SEARCH_TOKENS, "array-contains", searchTokens[0]);
126
127
  }
127
128
  else if (searchTokens.length > 1) {
128
- baseQuery = baseQuery.where("searchTokens", "array-contains-any", searchTokens);
129
+ baseQuery = baseQuery.where(FAQ_FIELDS.SEARCH_TOKENS, "array-contains-any", searchTokens);
129
130
  }
130
131
  return this.sieveQuery(model, FirebaseFAQsRepository.SIEVE_FIELDS, { baseQuery });
131
132
  }
@@ -142,53 +143,53 @@ export class FirebaseFAQsRepository extends BaseRepository {
142
143
  async getFAQsByCategory(category) {
143
144
  const snapshot = await this.db
144
145
  .collection(this.collection)
145
- .where("category", "==", category)
146
- .where("isActive", "==", true)
147
- .orderBy("order", "asc")
146
+ .where(FAQ_FIELDS.CATEGORY, "==", category)
147
+ .where(FAQ_FIELDS.IS_ACTIVE, "==", true)
148
+ .orderBy(FAQ_FIELDS.ORDER, "asc")
148
149
  .get();
149
150
  return snapshot.docs.map((doc) => this.mapDoc(doc));
150
151
  }
151
152
  async getHomepageFAQs() {
152
153
  const snapshot = await this.db
153
154
  .collection(this.collection)
154
- .where("showOnHomepage", "==", true)
155
- .where("isActive", "==", true)
156
- .orderBy("priority", "desc")
155
+ .where(FAQ_FIELDS.SHOW_ON_HOMEPAGE, "==", true)
156
+ .where(FAQ_FIELDS.IS_ACTIVE, "==", true)
157
+ .orderBy(FAQ_FIELDS.PRIORITY, "desc")
157
158
  .get();
158
159
  return snapshot.docs.map((doc) => this.mapDoc(doc));
159
160
  }
160
161
  async getFooterFAQs() {
161
162
  const snapshot = await this.db
162
163
  .collection(this.collection)
163
- .where("showInFooter", "==", true)
164
- .where("isActive", "==", true)
165
- .orderBy("order", "asc")
164
+ .where(FAQ_FIELDS.SHOW_IN_FOOTER, "==", true)
165
+ .where(FAQ_FIELDS.IS_ACTIVE, "==", true)
166
+ .orderBy(FAQ_FIELDS.ORDER, "asc")
166
167
  .get();
167
168
  return snapshot.docs.map((doc) => this.mapDoc(doc));
168
169
  }
169
170
  async getPinnedFAQs(category) {
170
171
  let query = this.db
171
172
  .collection(this.collection)
172
- .where("isPinned", "==", true)
173
- .where("isActive", "==", true);
173
+ .where(FAQ_FIELDS.IS_PINNED, "==", true)
174
+ .where(FAQ_FIELDS.IS_ACTIVE, "==", true);
174
175
  if (category) {
175
- query = query.where("category", "==", category);
176
+ query = query.where(FAQ_FIELDS.CATEGORY, "==", category);
176
177
  }
177
- const snapshot = await query.orderBy("order", "asc").get();
178
+ const snapshot = await query.orderBy(FAQ_FIELDS.ORDER, "asc").get();
178
179
  return snapshot.docs.map((doc) => this.mapDoc(doc));
179
180
  }
180
181
  async searchByTag(tag) {
181
182
  const snapshot = await this.db
182
183
  .collection(this.collection)
183
- .where("tags", "array-contains", tag)
184
- .where("isActive", "==", true)
184
+ .where(FAQ_FIELDS.TAGS, "array-contains", tag)
185
+ .where(FAQ_FIELDS.IS_ACTIVE, "==", true)
185
186
  .get();
186
187
  return snapshot.docs.map((doc) => this.mapDoc(doc));
187
188
  }
188
189
  async getMostHelpful(limit = 10) {
189
190
  const snapshot = await this.db
190
191
  .collection(this.collection)
191
- .where("isActive", "==", true)
192
+ .where(FAQ_FIELDS.IS_ACTIVE, "==", true)
192
193
  .orderBy("stats.helpful", "desc")
193
194
  .limit(limit)
194
195
  .get();
@@ -103,8 +103,8 @@ export declare const faqSchema: z.ZodObject<{
103
103
  seo?: {
104
104
  slug?: string | undefined;
105
105
  } | undefined;
106
- showInFooter?: boolean | undefined;
107
106
  showOnHomepage?: boolean | undefined;
107
+ showInFooter?: boolean | undefined;
108
108
  isPinned?: boolean | undefined;
109
109
  relatedFAQs?: string[] | undefined;
110
110
  }, {
@@ -129,8 +129,8 @@ export declare const faqSchema: z.ZodObject<{
129
129
  seo?: {
130
130
  slug?: string | undefined;
131
131
  } | undefined;
132
- showInFooter?: boolean | undefined;
133
132
  showOnHomepage?: boolean | undefined;
133
+ showInFooter?: boolean | undefined;
134
134
  isPinned?: boolean | undefined;
135
135
  relatedFAQs?: string[] | undefined;
136
136
  }>;
@@ -18,5 +18,7 @@ export function Slider({ value: controlledValue, defaultValue = 0, min = 0, max
18
18
  onChange?.(newVal);
19
19
  };
20
20
  const displayValue = formatValue ? formatValue(value) : String(value);
21
- return (_jsxs(Div, { className: cn("w-full space-y-2", className), children: [(label || showValue) && (_jsxs(Row, { justify: "between", children: [label && (_jsx("label", { htmlFor: sliderId, className: LABEL_BASE, children: label })), showValue && (_jsx(Span, { size: "sm", weight: "semibold", className: "tabular-nums text-zinc-900 dark:text-zinc-100", children: displayValue }))] })), _jsxs(Row, { className: "relative h-5", children: [_jsx(Div, { className: "absolute inset-y-0 flex items-center w-full", children: _jsx(Div, { className: "w-full h-1.5 rounded-full bg-zinc-200 dark:bg-slate-700", children: _jsx(Div, { className: "h-full rounded-full bg-primary-500 dark:bg-secondary-500 transition-all", style: { width: `${pct}%` } }) }) }), _jsx("input", { type: "range", id: sliderId, min: min, max: max, step: step, value: value, disabled: disabled, onChange: handleChange, className: cn("relative w-full appearance-none bg-transparent cursor-pointer", "focus:outline-none", "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", "[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-500 dark:[&::-webkit-slider-thumb]:border-secondary-500", "[&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4", "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white", "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary-500 dark:[&::-moz-range-thumb]:border-secondary-500", disabled && "opacity-50 cursor-not-allowed") })] }), _jsxs(Row, { justify: "between", className: "text-xs text-zinc-400 dark:text-zinc-400", children: [_jsx(Span, { children: formatValue ? formatValue(min) : min }), _jsx(Span, { children: formatValue ? formatValue(max) : max })] }), error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error }))] }));
21
+ return (_jsxs(Div, { className: cn("w-full space-y-2", className), children: [(label || showValue) && (_jsxs(Row, { justify: "between", children: [label && (_jsx("label", { htmlFor: sliderId, className: LABEL_BASE, children: label })), showValue && (_jsx(Span, { size: "sm", weight: "semibold", className: "tabular-nums text-zinc-900 dark:text-zinc-100", children: displayValue }))] })), _jsxs(Row, { className: "relative h-5", children: [_jsx(Div, { className: "absolute inset-y-0 flex items-center w-full", children: _jsx(Div, { className: "w-full h-1.5 rounded-full bg-zinc-200 dark:bg-slate-700", children: _jsx(Div, { className: "h-full rounded-full bg-primary-500 dark:bg-secondary-500 transition-all",
22
+ // audit-inline-style-ok: computed percentage
23
+ style: { width: `${pct}%` } }) }) }), _jsx("input", { type: "range", id: sliderId, min: min, max: max, step: step, value: value, disabled: disabled, onChange: handleChange, className: cn("relative w-full appearance-none bg-transparent cursor-pointer", "focus:outline-none", "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", "[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-500 dark:[&::-webkit-slider-thumb]:border-secondary-500", "[&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4", "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white", "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary-500 dark:[&::-moz-range-thumb]:border-secondary-500", disabled && "opacity-50 cursor-not-allowed") })] }), _jsxs(Row, { justify: "between", className: "text-xs text-zinc-400 dark:text-zinc-400", children: [_jsx(Span, { children: formatValue ? formatValue(min) : min }), _jsx(Span, { children: formatValue ? formatValue(max) : max })] }), error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error }))] }));
22
24
  }
@@ -69,6 +69,7 @@ export function useHistory(userId) {
69
69
  const [items, setItems] = useState([]);
70
70
  const trackTimers = useRef(new Map());
71
71
  const loadItems = useCallback(async () => {
72
+ // toast-intentionally-silent — silent fallback to empty list on error
72
73
  try {
73
74
  if (isAuth) {
74
75
  setItems(await fetchAuthHistory());
@@ -20,11 +20,15 @@ function AdsenseAd({ config }) {
20
20
  // AdSense not loaded yet — no-op
21
21
  }
22
22
  }, []);
23
- return (_jsx(Div, { ref: ref, children: _jsx("ins", { className: "adsbygoogle", style: { display: "block" }, "data-ad-client": config.adsenseClient ?? "", "data-ad-slot": config.adsenseSlot ?? "", "data-ad-format": config.adsenseFormat ?? "auto", "data-full-width-responsive": "true" }) }));
23
+ return (_jsx(Div, { ref: ref, children: _jsx("ins", { className: "adsbygoogle",
24
+ // audit-inline-style-ok: dynamic CSS
25
+ style: { display: "block" }, "data-ad-client": config.adsenseClient ?? "", "data-ad-slot": config.adsenseSlot ?? "", "data-ad-format": config.adsenseFormat ?? "auto", "data-full-width-responsive": "true" }) }));
24
26
  }
25
27
  function ThirdPartyAd({ config }) {
26
28
  if (config.thirdPartyUrl) {
27
- return (_jsx("iframe", { src: config.thirdPartyUrl, width: config.thirdPartyWidth ?? "100%", height: config.thirdPartyHeight ?? "90", scrolling: "no", frameBorder: "0", title: "Advertisement", style: { border: 0, overflow: "hidden" }, loading: "lazy" }));
29
+ return (_jsx("iframe", { src: config.thirdPartyUrl, width: config.thirdPartyWidth ?? "100%", height: config.thirdPartyHeight ?? "90", scrolling: "no", frameBorder: "0", title: "Advertisement",
30
+ // audit-inline-style-ok: dynamic CSS
31
+ style: { border: 0, overflow: "hidden" }, loading: "lazy" }));
28
32
  }
29
33
  return null;
30
34
  }
@@ -30,5 +30,7 @@ export function AdvertisementBanner({ title, subtitle, ctaLabel = "Shop now", on
30
30
  compact
31
31
  ? "h-[clamp(112px,16vh,160px)]"
32
32
  : "min-h-[clamp(240px,34vh,360px)]",
33
- ].join(" "), style: backgroundColor ? { backgroundColor } : undefined, children: [!backgroundColor && (_jsx(Div, { className: CLS_GRADIENT_BG, "aria-hidden": true })), _jsxs(Div, { className: `absolute inset-0 ${__O.hidden}`, "aria-hidden": true, children: [_jsx(Div, { className: "absolute -top-16 -left-16 w-64 h-64 rounded-full bg-primary/20 blur-3xl animate-pulse" }), _jsx(Div, { className: "absolute -bottom-16 right-0 w-80 h-80 rounded-full bg-cobalt/20 blur-3xl animate-pulse" })] }), compact ? (_jsxs(Row, { justify: "between", className: "relative z-10 w-full px-6 py-4 gap-4 flex-wrap", children: [_jsxs(Span, { className: "inline-flex items-center gap-2", children: [_jsx(Sparkles, { className: "w-4 h-4 text-white/80" }), _jsx(Span, { size: "sm", weight: "semibold", className: "text-white", children: title })] }), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "sm", onClick: onCtaClick, className: CLS_CTA_BTN_SM, children: [ctaLabel, _jsx(ArrowRight, { className: "w-3.5 h-3.5" })] }))] })) : (_jsxs(Div, { className: "relative z-10 w-full max-w-4xl mx-auto px-6 py-12 md:py-16 text-center", children: [tagLabel && (_jsxs(Span, { size: "xs", weight: "semibold", className: "inline-flex items-center gap-1.5 bg-white/15 text-white/90 uppercase tracking-widest px-4 py-1.5 rounded-full mb-5 backdrop-blur-sm shadow-sm", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-5xl lg:text-6xl font-extrabold text-white mb-4 drop-shadow-lg leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white text-base md:text-xl mb-10 max-w-2xl mx-auto", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: CLS_CTA_BTN_LG, children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] }))] }) }) }));
33
+ ].join(" "),
34
+ // audit-inline-style-ok: optional inline color
35
+ style: backgroundColor ? { backgroundColor } : undefined, children: [!backgroundColor && (_jsx(Div, { className: CLS_GRADIENT_BG, "aria-hidden": true })), _jsxs(Div, { className: `absolute inset-0 ${__O.hidden}`, "aria-hidden": true, children: [_jsx(Div, { className: "absolute -top-16 -left-16 w-64 h-64 rounded-full bg-primary/20 blur-3xl animate-pulse" }), _jsx(Div, { className: "absolute -bottom-16 right-0 w-80 h-80 rounded-full bg-cobalt/20 blur-3xl animate-pulse" })] }), compact ? (_jsxs(Row, { justify: "between", className: "relative z-10 w-full px-6 py-4 gap-4 flex-wrap", children: [_jsxs(Span, { className: "inline-flex items-center gap-2", children: [_jsx(Sparkles, { className: "w-4 h-4 text-white/80" }), _jsx(Span, { size: "sm", weight: "semibold", className: "text-white", children: title })] }), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "sm", onClick: onCtaClick, className: CLS_CTA_BTN_SM, children: [ctaLabel, _jsx(ArrowRight, { className: "w-3.5 h-3.5" })] }))] })) : (_jsxs(Div, { className: "relative z-10 w-full max-w-4xl mx-auto px-6 py-12 md:py-16 text-center", children: [tagLabel && (_jsxs(Span, { size: "xs", weight: "semibold", className: "inline-flex items-center gap-1.5 bg-white/15 text-white/90 uppercase tracking-widest px-4 py-1.5 rounded-full mb-5 backdrop-blur-sm shadow-sm", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-5xl lg:text-6xl font-extrabold text-white mb-4 drop-shadow-lg leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white text-base md:text-xl mb-10 max-w-2xl mx-auto", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: CLS_CTA_BTN_LG, children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] }))] }) }) }));
34
36
  }
@@ -55,5 +55,9 @@ export function BeforeAfterCard({ item, beforeLabel = "Before", afterLabel = "Af
55
55
  setPosition((p) => Math.max(0, p - 2));
56
56
  if (e.key === "ArrowRight")
57
57
  setPosition((p) => Math.min(100, p + 2));
58
- }, children: [_jsx(Image, { src: item.afterImage, alt: afterLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }), _jsx(Div, { className: "absolute inset-0 overflow-hidden", style: { width: `${position}%` }, children: _jsx(Image, { src: item.beforeImage, alt: beforeLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }) }), _jsx(Div, { className: "absolute top-0 bottom-0 z-10 w-0.5 bg-card shadow-md", style: { left: `${position}%` }, children: _jsx(Div, { className: "absolute top-1/2 left-1/2 flex h-8 w-8 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-card shadow-lg", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 8L1 5M4 8L1 11M4 8H12M12 8L15 5M12 8L15 11", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute top-3 left-3 z-10 rounded-full bg-black/50 px-2.5 py-0.5 text-white", children: beforeLabel }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute top-3 right-3 z-10 rounded-full bg-black/50 px-2.5 py-0.5 text-white", children: afterLabel })] }), _jsx(Div, { className: `${__P.p4}`, children: _jsx(Text, { className: "text-foreground text-sm font-medium", children: item.caption }) })] }));
58
+ }, children: [_jsx(Image, { src: item.afterImage, alt: afterLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }), _jsx(Div, { className: "absolute inset-0 overflow-hidden",
59
+ // audit-inline-style-ok: computed percentage
60
+ style: { width: `${position}%` }, children: _jsx(Image, { src: item.beforeImage, alt: beforeLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }) }), _jsx(Div, { className: "absolute top-0 bottom-0 z-10 w-0.5 bg-card shadow-md",
61
+ // audit-inline-style-ok: computed percentage
62
+ style: { left: `${position}%` }, children: _jsx(Div, { className: "absolute top-1/2 left-1/2 flex h-8 w-8 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-card shadow-lg", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 8L1 5M4 8L1 11M4 8H12M12 8L15 5M12 8L15 11", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute top-3 left-3 z-10 rounded-full bg-black/50 px-2.5 py-0.5 text-white", children: beforeLabel }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute top-3 right-3 z-10 rounded-full bg-black/50 px-2.5 py-0.5 text-white", children: afterLabel })] }), _jsx(Div, { className: `${__P.p4}`, children: _jsx(Text, { className: "text-foreground text-sm font-medium", children: item.caption }) })] }));
59
63
  }
@@ -47,7 +47,11 @@ function CardItem({ card }) {
47
47
  cardStyle.backgroundColor = card.backgroundColor;
48
48
  if (card.textColor)
49
49
  cardStyle.color = card.textColor;
50
- return (_jsxs(Div, { className: `flex flex-col overflow-hidden ${radiusClass} ${shadowClass} bg-[var(--appkit-color-surface)]`, style: cardStyle, children: [card.image && (_jsx(Div, { className: `relative w-full aspect-video ${__O.hidden}`, children: _jsx(MediaImage, { src: card.image, alt: card.imageAlt ?? "", size: "card" }) })), _jsxs(Div, { className: `flex flex-col gap-2 ${__P.p4} flex-1`, children: [card.eyebrow && (_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest opacity-70", children: card.eyebrow })), card.title && (_jsx(Text, { className: "text-base font-bold leading-snug", children: card.title })), card.body && (_jsx(Text, { className: "text-sm opacity-80 leading-relaxed flex-1", children: card.body })), card.buttons && card.buttons.length > 0 && (_jsx(Div, { className: "flex flex-wrap gap-2 mt-2", children: card.buttons.map((btn, i) => (_jsx("a", { href: btn.href, target: btn.target ?? "_self", rel: btn.target === "_blank" ? "noopener noreferrer" : undefined, className: VARIANT_CLASS[btn.variant] ?? VARIANT_CLASS.primary, children: btn.label }, i))) })), card.formEmbed && (_jsx("iframe", { src: card.formEmbed, sandbox: "allow-forms allow-scripts", loading: "lazy", className: "w-full mt-3 border-0 rounded-md", style: { minHeight: "200px" }, title: "Embedded form" }))] })] }));
50
+ return (_jsxs(Div, { className: `flex flex-col overflow-hidden ${radiusClass} ${shadowClass} bg-[var(--appkit-color-surface)]`,
51
+ // audit-inline-style-ok: pass-through style prop
52
+ style: cardStyle, children: [card.image && (_jsx(Div, { className: `relative w-full aspect-video ${__O.hidden}`, children: _jsx(MediaImage, { src: card.image, alt: card.imageAlt ?? "", size: "card" }) })), _jsxs(Div, { className: `flex flex-col gap-2 ${__P.p4} flex-1`, children: [card.eyebrow && (_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest opacity-70", children: card.eyebrow })), card.title && (_jsx(Text, { className: "text-base font-bold leading-snug", children: card.title })), card.body && (_jsx(Text, { className: "text-sm opacity-80 leading-relaxed flex-1", children: card.body })), card.buttons && card.buttons.length > 0 && (_jsx(Div, { className: "flex flex-wrap gap-2 mt-2", children: card.buttons.map((btn, i) => (_jsx("a", { href: btn.href, target: btn.target ?? "_self", rel: btn.target === "_blank" ? "noopener noreferrer" : undefined, className: VARIANT_CLASS[btn.variant] ?? VARIANT_CLASS.primary, children: btn.label }, i))) })), card.formEmbed && (_jsx("iframe", { src: card.formEmbed, sandbox: "allow-forms allow-scripts", loading: "lazy", className: "w-full mt-3 border-0 rounded-md",
53
+ // audit-inline-style-ok: dynamic CSS
54
+ style: { minHeight: "200px" }, title: "Embedded form" }))] })] }));
51
55
  }
52
56
  // --- Section Header ----------------------------------------------------------
53
57
  function SectionHeader({ title }) {
@@ -14,7 +14,9 @@ function StepCard({ step, visible, delay, }) {
14
14
  "shadow-md group hover:-translate-y-2 hover:shadow-xl",
15
15
  "transition-all duration-300",
16
16
  visible ? CLS_VISIBLE : "opacity-0 translate-y-8",
17
- ].join(" "), style: { transitionDelay: `${delay}ms` }, "data-section": "howitworkssection-div-340", children: [_jsx(Div, { className: "absolute top-4 right-5 font-display text-7xl bg-gradient-to-br from-primary to-cobalt opacity-10 bg-clip-text text-transparent select-none pointer-events-none leading-none", "aria-hidden": "true", children: step.number }), _jsx(Div, { className: `relative z-10 w-10 h-10 rounded-full ${badgeBg} text-white font-bold text-sm flex items-center justify-center mb-5 shadow-md`, children: step.number }), step.renderIcon && (_jsx(Div, { className: `relative z-10 w-14 h-14 rounded-2xl ${iconBg} flex items-center justify-center mb-4 border border-white/80 dark:border-slate-700/50`, children: _jsx("span", { className: `${iconColor}`, "aria-hidden": "true", children: step.renderIcon({ className: "w-6 h-6" }) }) })), _jsx(Heading, { level: 3, className: `relative z-10 text-base font-semibold ${THEME_CONSTANTS.themed.textPrimary} mb-2`, children: step.title }), _jsx(Text, { className: `relative z-10 text-sm ${THEME_CONSTANTS.themed.textSecondary} leading-relaxed`, children: step.desc })] }));
17
+ ].join(" "),
18
+ // audit-inline-style-ok: computed timing
19
+ style: { transitionDelay: `${delay}ms` }, "data-section": "howitworkssection-div-340", children: [_jsx(Div, { className: "absolute top-4 right-5 font-display text-7xl bg-gradient-to-br from-primary to-cobalt opacity-10 bg-clip-text text-transparent select-none pointer-events-none leading-none", "aria-hidden": "true", children: step.number }), _jsx(Div, { className: `relative z-10 w-10 h-10 rounded-full ${badgeBg} text-white font-bold text-sm flex items-center justify-center mb-5 shadow-md`, children: step.number }), step.renderIcon && (_jsx(Div, { className: `relative z-10 w-14 h-14 rounded-2xl ${iconBg} flex items-center justify-center mb-4 border border-white/80 dark:border-slate-700/50`, children: _jsx("span", { className: `${iconColor}`, "aria-hidden": "true", children: step.renderIcon({ className: "w-6 h-6" }) }) })), _jsx(Heading, { level: 3, className: `relative z-10 text-base font-semibold ${THEME_CONSTANTS.themed.textPrimary} mb-2`, children: step.title }), _jsx(Text, { className: `relative z-10 text-sm ${THEME_CONSTANTS.themed.textSecondary} leading-relaxed`, children: step.desc })] }));
18
20
  }
19
21
  // --- Section -----------------------------------------------------------------
20
22
  export function HowItWorksSection({ title, subtitle, pillLabel, ctaLabel, onCtaClick, steps, className = "", }) {