@mohasinac/appkit 3.0.0 → 3.0.2

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 (336) hide show
  1. package/dist/_internal/client/features/layout/SidebarCollapseToggle.js +1 -5
  2. package/dist/_internal/server/features/auctions/actions.js +0 -1
  3. package/dist/_internal/server/features/auctions/og.js +0 -1
  4. package/dist/_internal/server/features/auctions/service.js +0 -4
  5. package/dist/_internal/server/features/auth/capabilities.js +0 -1
  6. package/dist/_internal/server/features/blog/actions.js +0 -2
  7. package/dist/_internal/server/features/brands/actions.js +0 -2
  8. package/dist/_internal/server/features/cart/actions.js +0 -3
  9. package/dist/_internal/server/features/checkout/actions.js +11 -20
  10. package/dist/_internal/server/features/events/actions.js +0 -3
  11. package/dist/_internal/server/features/events/og.js +0 -1
  12. package/dist/_internal/server/features/events/service.js +0 -2
  13. package/dist/_internal/server/features/grouped/data.js +0 -2
  14. package/dist/_internal/server/features/orders/actions.js +0 -4
  15. package/dist/_internal/server/features/pre-orders/actions.js +0 -1
  16. package/dist/_internal/server/features/pre-orders/og.js +0 -1
  17. package/dist/_internal/server/features/pre-orders/service.js +0 -1
  18. package/dist/_internal/server/features/products/actions.js +0 -6
  19. package/dist/_internal/server/features/products/service.js +0 -1
  20. package/dist/_internal/server/features/promotions/actions.js +0 -3
  21. package/dist/_internal/server/features/reviews/actions.js +0 -3
  22. package/dist/_internal/server/functions/https.js +0 -6
  23. package/dist/_internal/server/functions/manifest.js +0 -1
  24. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +1 -1
  25. package/dist/_internal/server/jobs/core/wrapJobHandler.js +0 -1
  26. package/dist/_internal/shared/listing-types/action-tracker.js +1 -1
  27. package/dist/_internal/shared/serialization/index.js +0 -4
  28. package/dist/_internal/shared/styles/themed.js +0 -3
  29. package/dist/client/api/ApiError.js +1 -4
  30. package/dist/client/api/surface-error.js +0 -1
  31. package/dist/client/api/useApiQuery.js +0 -1
  32. package/dist/configs/next.js +0 -1
  33. package/dist/configs/tailwind.js +0 -1
  34. package/dist/contracts/field-ops.js +0 -2
  35. package/dist/core/EventBus.js +0 -2
  36. package/dist/core/Logger.js +0 -6
  37. package/dist/core/Queue.js +0 -2
  38. package/dist/core/hooks/useSyncManager.js +4 -4
  39. package/dist/core/mutation-events.js +0 -1
  40. package/dist/core/newsletter.repository.js +2 -6
  41. package/dist/errors/api-error.js +0 -1
  42. package/dist/errors/authentication-error.js +0 -1
  43. package/dist/errors/authorization-error.js +0 -1
  44. package/dist/errors/base-error.js +1 -3
  45. package/dist/errors/database-error.js +0 -1
  46. package/dist/errors/error-handler.js +1 -5
  47. package/dist/errors/error-mapping.js +1 -6
  48. package/dist/errors/normalize.js +0 -4
  49. package/dist/errors/not-found-error.js +0 -1
  50. package/dist/errors/razorpay-unreachable.js +0 -1
  51. package/dist/errors/validation-error.js +0 -1
  52. package/dist/features/about/components/FAQPageView.js +1 -3
  53. package/dist/features/about/components/FeesView.js +1 -3
  54. package/dist/features/about/components/HelpPageView.js +1 -3
  55. package/dist/features/about/components/PublicProfileView.js +4 -4
  56. package/dist/features/account/components/AddressBook.js +1 -3
  57. package/dist/features/account/components/AddressForm.js +0 -1
  58. package/dist/features/account/components/AddressesIndexListing.js +0 -1
  59. package/dist/features/account/components/MessagesView.js +1 -3
  60. package/dist/features/account/components/NotificationBell.js +3 -14
  61. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  62. package/dist/features/account/components/UserOffersPanel.js +0 -2
  63. package/dist/features/account/components/UserSidebar.js +1 -3
  64. package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
  65. package/dist/features/admin/components/AdminBundleEditorView.js +0 -1
  66. package/dist/features/admin/components/AdminBundlesView.js +0 -1
  67. package/dist/features/admin/components/AdminCarouselEditorView.js +1 -5
  68. package/dist/features/admin/components/AdminCarouselView.js +1 -4
  69. package/dist/features/admin/components/AdminCartsView.js +0 -1
  70. package/dist/features/admin/components/AdminMediaView.js +1 -3
  71. package/dist/features/admin/components/AdminPayoutsView.js +0 -1
  72. package/dist/features/admin/components/AdminProductsView.js +1 -3
  73. package/dist/features/admin/components/AdminSidebar.js +1 -3
  74. package/dist/features/admin/components/AdminSiteSettingsView.js +1 -5
  75. package/dist/features/admin/components/AdminSupportTicketDetailView.js +7 -13
  76. package/dist/features/admin/components/DashboardStats.js +1 -7
  77. package/dist/features/admin/components/DataListingView.js +1 -5
  78. package/dist/features/admin/components/DataTable.js +1 -3
  79. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +1 -3
  80. package/dist/features/admin/components/analytics/AdminStatCard.js +1 -7
  81. package/dist/features/admin/components/analytics/AdminTopProductsTable.js +1 -3
  82. package/dist/features/admin/components/sections/adminSectionsBuildParse.js +0 -5
  83. package/dist/features/admin/hooks/useAdminListingData.js +0 -5
  84. package/dist/features/admin/hooks/useChat.js +0 -3
  85. package/dist/features/admin/repository/chat.repository.js +0 -1
  86. package/dist/features/admin/repository/notification.repository.js +1 -4
  87. package/dist/features/auctions/components/AuctionBidsTable.js +1 -7
  88. package/dist/features/auctions/components/AuctionDetailPageView.js +1 -6
  89. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -15
  90. package/dist/features/auctions/components/PlaceBidFormClient.js +0 -3
  91. package/dist/features/auctions/repository/bid.repository.js +0 -1
  92. package/dist/features/auth/components/ForgotPasswordView.js +0 -1
  93. package/dist/features/auth/components/LoginForm.js +0 -1
  94. package/dist/features/auth/components/RegisterForm.js +0 -1
  95. package/dist/features/auth/components/ResetPasswordView.js +0 -1
  96. package/dist/features/auth/hooks/useAuth.js +0 -1
  97. package/dist/features/auth/repository/session.repository.js +0 -1
  98. package/dist/features/auth/repository/token.repository.js +0 -2
  99. package/dist/features/auth/repository/user.repository.js +0 -1
  100. package/dist/features/blog/api/[slug]/route.js +1 -1
  101. package/dist/features/blog/components/BlogFeaturedCard.js +1 -5
  102. package/dist/features/blog/components/BlogIndexListing.js +0 -1
  103. package/dist/features/blog/components/BlogListView.js +1 -5
  104. package/dist/features/blog/components/BlogPostView.js +1 -3
  105. package/dist/features/cart/components/CartDrawer.js +2 -6
  106. package/dist/features/cart/repository/cart.repository.js +0 -1
  107. package/dist/features/categories/api/route.js +0 -1
  108. package/dist/features/categories/components/BrandDetailPageView.js +1 -13
  109. package/dist/features/categories/components/BundleDetailView.js +1 -5
  110. package/dist/features/categories/components/BundleItemsPicker.js +1 -5
  111. package/dist/features/categories/components/CategoriesIndexListing.js +0 -1
  112. package/dist/features/categories/components/CategoriesIndexPageView.js +0 -1
  113. package/dist/features/categories/components/CategoryBundlesListing.js +1 -3
  114. package/dist/features/categories/components/CategoryDetailPageView.js +1 -16
  115. package/dist/features/categories/components/CategoryGrid.js +1 -5
  116. package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
  117. package/dist/features/categories/components/CategoryTableColumns.js +2 -6
  118. package/dist/features/categories/components/CategoryTree.js +1 -3
  119. package/dist/features/categories/components/ConcernCard.js +1 -3
  120. package/dist/features/collections/components/CollectionCard.js +1 -5
  121. package/dist/features/contact/email.js +0 -1
  122. package/dist/features/events/actions/event-actions.js +0 -1
  123. package/dist/features/events/api/[id]/route.js +0 -1
  124. package/dist/features/events/components/AdminEventEditorView.js +13 -14
  125. package/dist/features/events/components/EventCard.js +2 -8
  126. package/dist/features/events/components/EventRaffleEntryForm.js +1 -3
  127. package/dist/features/events/components/EventRaffleWinnerView.js +1 -3
  128. package/dist/features/events/components/EventRafflesSection.js +0 -1
  129. package/dist/features/events/components/EventsIndexListing.js +0 -1
  130. package/dist/features/events/hooks/useBulkEvent.js +0 -1
  131. package/dist/features/events/repository/event-entry.repository.js +0 -1
  132. package/dist/features/faq/components/ContactCTA.js +1 -3
  133. package/dist/features/faq/components/FAQAccordion.js +1 -3
  134. package/dist/features/faq/components/FAQCategorySidebar.js +1 -3
  135. package/dist/features/faq/components/RelatedFAQs.js +1 -5
  136. package/dist/features/filters/AsyncFacetSection.js +1 -3
  137. package/dist/features/filters/FilterFacetSection.js +4 -14
  138. package/dist/features/forms/Checkbox.js +1 -3
  139. package/dist/features/forms/Slider.js +1 -3
  140. package/dist/features/history/hooks/useHistory.js +0 -1
  141. package/dist/features/history/repository/user-history.repository.js +0 -2
  142. package/dist/features/homepage/actions/carousel-actions.js +0 -1
  143. package/dist/features/homepage/actions/homepage-section-actions.js +1 -3
  144. package/dist/features/homepage/api/carousel/route.js +0 -1
  145. package/dist/features/homepage/api/route.js +0 -1
  146. package/dist/features/homepage/components/AdSlot.js +3 -9
  147. package/dist/features/homepage/components/AdvertisementBanner.js +2 -12
  148. package/dist/features/homepage/components/BeforeAfterCard.js +1 -5
  149. package/dist/features/homepage/components/CharacterHotspotForm.js +2 -10
  150. package/dist/features/homepage/components/CollectionCardsSection.js +1 -3
  151. package/dist/features/homepage/components/CustomCardsSection.js +1 -5
  152. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -3
  153. package/dist/features/homepage/components/GoogleReviewsSection.js +1 -3
  154. package/dist/features/homepage/components/HeroCarousel.js +5 -26
  155. package/dist/features/homepage/components/HeroSection.js +2 -6
  156. package/dist/features/homepage/components/HowItWorksSection.js +2 -8
  157. package/dist/features/homepage/components/MarketplaceHomepageView.js +0 -8
  158. package/dist/features/homepage/components/NewsletterBanner.js +2 -10
  159. package/dist/features/homepage/components/PromoGrid.js +1 -3
  160. package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -6
  161. package/dist/features/homepage/components/ShopByCategorySection.js +2 -6
  162. package/dist/features/homepage/components/SocialPostCard.js +1 -3
  163. package/dist/features/homepage/components/StatsCounterSection.js +1 -5
  164. package/dist/features/homepage/components/TrustBadges.js +1 -3
  165. package/dist/features/homepage/components/TrustFeaturesSection.js +1 -3
  166. package/dist/features/homepage/components/WelcomeSection.js +2 -16
  167. package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -5
  168. package/dist/features/homepage/lib/social-feed-fetcher.js +0 -8
  169. package/dist/features/layout/AppLayoutShell.js +1 -3
  170. package/dist/features/layout/BottomNavbar.js +1 -11
  171. package/dist/features/media/MediaAudio.js +2 -6
  172. package/dist/features/media/MediaImage.js +0 -1
  173. package/dist/features/media/MediaLightbox.js +3 -9
  174. package/dist/features/media/MediaVideo.js +2 -8
  175. package/dist/features/media/upload/MediaUploadField.js +1 -3
  176. package/dist/features/messages/hooks/useConversation.js +0 -2
  177. package/dist/features/messages/hooks/useConversations.js +0 -1
  178. package/dist/features/messages/repository/conversations.repository.js +0 -1
  179. package/dist/features/orders/api/track/[trackingId]/route.js +0 -1
  180. package/dist/features/orders/components/OrdersList.js +1 -3
  181. package/dist/features/orders/components/RefundHistoryTable.js +1 -3
  182. package/dist/features/orders/repository/orders.repository.js +0 -2
  183. package/dist/features/payments/repository/payout.repository.js +0 -1
  184. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +2 -6
  185. package/dist/features/pre-orders/components/PreOrderActionsClient.js +0 -1
  186. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -3
  187. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -5
  188. package/dist/features/products/api/route.js +1 -3
  189. package/dist/features/products/components/CompareOverlay.js +1 -6
  190. package/dist/features/products/components/FeatureBadge.js +1 -3
  191. package/dist/features/products/components/MakeOfferButton.js +0 -2
  192. package/dist/features/products/components/MarketplaceBundleCard.js +1 -3
  193. package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -3
  194. package/dist/features/products/components/PrizeDrawDetailPageView.js +0 -2
  195. package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -3
  196. package/dist/features/products/components/PrizeDrawsSection.js +1 -3
  197. package/dist/features/products/components/ProductDetailPageView.js +0 -6
  198. package/dist/features/products/components/ProductFeatureBadges.js +1 -3
  199. package/dist/features/products/components/ProductFeaturesSelector.js +0 -1
  200. package/dist/features/products/components/ProductGrid.js +5 -15
  201. package/dist/features/products/components/ShareButton.js +1 -1
  202. package/dist/features/products/components/ShowGroupSection.js +3 -7
  203. package/dist/features/products/components/SublistingCarouselSection.js +2 -4
  204. package/dist/features/products/repository/product-features.repository.js +0 -1
  205. package/dist/features/products/repository/products.repository.js +0 -1
  206. package/dist/features/promotions/components/CouponCard.js +2 -5
  207. package/dist/features/promotions/repository/coupons.repository.js +0 -1
  208. package/dist/features/reviews/api/route.js +0 -1
  209. package/dist/features/reviews/components/ReviewDetailShell.js +3 -13
  210. package/dist/features/reviews/components/ReviewModal.js +1 -5
  211. package/dist/features/reviews/components/ReviewSummary.js +2 -6
  212. package/dist/features/reviews/components/ReviewsIndexListing.js +0 -1
  213. package/dist/features/reviews/components/ReviewsList.js +1 -7
  214. package/dist/features/reviews/repository/reviews.repository.js +0 -3
  215. package/dist/features/scams/actions/scam-actions.js +1 -1
  216. package/dist/features/scams/components/ScamProfileView.js +1 -3
  217. package/dist/features/search/components/Search.js +2 -8
  218. package/dist/features/search/components/SearchFiltersRow.js +1 -3
  219. package/dist/features/seller/components/PhysicalLocationModal.js +1 -5
  220. package/dist/features/seller/components/SellerAddressesView.js +1 -6
  221. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +1 -4
  222. package/dist/features/seller/components/SellerBidsView.js +1 -3
  223. package/dist/features/seller/components/SellerBundlesView.js +0 -1
  224. package/dist/features/seller/components/SellerCouponEditorView.js +1 -3
  225. package/dist/features/seller/components/SellerFeaturesView.js +0 -1
  226. package/dist/features/seller/components/SellerGoogleReviewsView.js +1 -1
  227. package/dist/features/seller/components/SellerLiveView.js +1 -3
  228. package/dist/features/seller/components/SellerOffersPanel.js +0 -2
  229. package/dist/features/seller/components/SellerOrdersView.js +1 -6
  230. package/dist/features/seller/components/SellerPayoutMethodsView.js +0 -1
  231. package/dist/features/seller/components/SellerPayoutRequestView.js +1 -1
  232. package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
  233. package/dist/features/seller/components/SellerProductShell.js +2 -4
  234. package/dist/features/seller/components/SellerProductsCards.js +1 -3
  235. package/dist/features/seller/components/SellerProductsView.js +1 -7
  236. package/dist/features/seller/components/SellerReviewsView.js +1 -4
  237. package/dist/features/seller/components/SellerShippingConfigsView.js +1 -4
  238. package/dist/features/seller/components/SellerShippingView.js +1 -1
  239. package/dist/features/seller/components/SellerSidebar.js +4 -12
  240. package/dist/features/seller/components/SellerStoreCategoriesView.js +0 -2
  241. package/dist/features/seller/components/SellerTemplatesView.js +0 -1
  242. package/dist/features/seller/components/analytics/SellerRevenueChart.js +1 -3
  243. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -3
  244. package/dist/features/seller/hooks/useSellerListingData.js +0 -5
  245. package/dist/features/seller/repository/offer.repository.js +0 -1
  246. package/dist/features/shell/FormShell.js +2 -15
  247. package/dist/features/shell/QuickFormDrawer.js +1 -5
  248. package/dist/features/site-settings/components/NavPermissionsManager.js +1 -3
  249. package/dist/features/site-settings/components/ThemeManagerView.js +0 -1
  250. package/dist/features/stores/api/[storeSlug]/reviews/route.js +0 -1
  251. package/dist/features/stores/components/StoreHeader.js +1 -7
  252. package/dist/features/stores/components/StoreReviewsListing.js +0 -1
  253. package/dist/features/stores/components/StoresIndexListing.js +0 -1
  254. package/dist/features/stores/repository/store.repository.js +0 -2
  255. package/dist/features/support/repository/support.repository.js +0 -1
  256. package/dist/features/wishlist/components/WishlistPage.js +1 -3
  257. package/dist/features/wishlist/hooks/useWishlistCount.js +1 -1
  258. package/dist/features/wishlist/repository/user-wishlist.repository.js +0 -2
  259. package/dist/http/ApiClient.js +4 -12
  260. package/dist/index.d.ts +1 -1
  261. package/dist/index.js +5 -3
  262. package/dist/monitoring/client-logger.js +7 -22
  263. package/dist/monitoring/error-tracking.js +0 -1
  264. package/dist/monitoring/performance.js +0 -1
  265. package/dist/monitoring/server-logger.js +11 -33
  266. package/dist/next/api/api-response.js +1 -4
  267. package/dist/next/api/apiHandler.js +1 -5
  268. package/dist/next/api/errorHandler.js +0 -3
  269. package/dist/next/api/parseJsonBody.js +0 -1
  270. package/dist/next/api/routeHandler.js +1 -6
  271. package/dist/next/cache-middleware.js +1 -3
  272. package/dist/next/middleware/chain.js +0 -1
  273. package/dist/next/middleware/pii-scrubber.js +0 -2
  274. package/dist/providers/auth-firebase/provider.js +0 -1
  275. package/dist/providers/db-firebase/admin.js +0 -1
  276. package/dist/providers/db-firebase/base.js +0 -4
  277. package/dist/providers/db-firebase/base.repository.js +0 -3
  278. package/dist/providers/db-firebase/field-ops.js +0 -2
  279. package/dist/providers/db-firebase/helpers.js +0 -4
  280. package/dist/providers/db-firebase/realtime.js +3 -15
  281. package/dist/providers/db-firebase/sieve.js +2 -8
  282. package/dist/providers/payment-razorpay/index.js +0 -3
  283. package/dist/providers/shipping-shiprocket/index.js +0 -1
  284. package/dist/providers/storage-firebase/client.js +0 -4
  285. package/dist/react/contexts/SessionContext.js +0 -1
  286. package/dist/react/hooks/useCountdown.js +0 -1
  287. package/dist/security/authorization.js +0 -1
  288. package/dist/security/pii-encrypt.js +0 -4
  289. package/dist/security/pii-redact.js +0 -3
  290. package/dist/seed/manifest.js +1 -6
  291. package/dist/seed/runner.js +0 -2
  292. package/dist/ui/DataTable.js +2 -6
  293. package/dist/ui/components/Anchor.js +0 -1
  294. package/dist/ui/components/AvatarDisplay.js +1 -3
  295. package/dist/ui/components/BackgroundRenderer.js +2 -6
  296. package/dist/ui/components/BaseListingCard.js +0 -1
  297. package/dist/ui/components/Button.js +0 -3
  298. package/dist/ui/components/Card.js +2 -6
  299. package/dist/ui/components/Details.js +2 -8
  300. package/dist/ui/components/Dialog.js +0 -1
  301. package/dist/ui/components/FallbackShell.js +5 -17
  302. package/dist/ui/components/Fieldset.js +2 -6
  303. package/dist/ui/components/HorizontalRule.js +0 -1
  304. package/dist/ui/components/HotspotMarker.js +1 -3
  305. package/dist/ui/components/IconBox.js +0 -1
  306. package/dist/ui/components/Iframe.js +0 -1
  307. package/dist/ui/components/ImageGallery.js +1 -3
  308. package/dist/ui/components/ImageLightbox.js +1 -5
  309. package/dist/ui/components/Kbd.js +0 -1
  310. package/dist/ui/components/Motion.js +1 -3
  311. package/dist/ui/components/NavbarChevron.js +0 -1
  312. package/dist/ui/components/PasswordStrengthIndicator.js +1 -3
  313. package/dist/ui/components/Progress.js +2 -6
  314. package/dist/ui/components/Quote.js +1 -4
  315. package/dist/ui/components/Responsive.js +0 -4
  316. package/dist/ui/components/RowActionMenu.js +1 -3
  317. package/dist/ui/components/Scrim.js +0 -1
  318. package/dist/ui/components/SiteLogo.js +1 -9
  319. package/dist/ui/components/Skeleton.js +1 -3
  320. package/dist/ui/components/Slider.js +1 -3
  321. package/dist/ui/components/StickyToolbar.js +0 -1
  322. package/dist/ui/components/TabStrip.js +1 -3
  323. package/dist/ui/components/Toast.js +1 -3
  324. package/dist/ui/components/Tooltip.js +1 -4
  325. package/dist/ui/components/UnsavedChangesModal.js +1 -3
  326. package/dist/ui/rich-text/RichText.js +1 -1
  327. package/dist/utils/action-response.js +0 -1
  328. package/dist/utils/date.formatter.js +0 -1
  329. package/dist/utils/object.helper.js +0 -2
  330. package/dist/utils/schema-ui.js +1 -3
  331. package/dist/validation/input.validator.js +0 -1
  332. package/dist/validation/schemas.js +1 -3
  333. package/package.json +5 -2
  334. package/scripts/bundle-css.mjs +47 -0
  335. package/scripts/copy-assets.mjs +34 -0
  336. package/scripts/dedupe-peer-deps.mjs +92 -0
@@ -88,9 +88,7 @@ export function MarketplacePrizeDrawCard({ product, className = "", variant = "g
88
88
  }
89
89
  router.push(String(detailHref));
90
90
  }, [detailHref, onNavigate, router]);
91
- return (_jsxs(BaseListingCard, { isSelected: isSelected, variant: variant, className: className, onMouseDown: !isSelected ? longPress.onMouseDown : undefined, onMouseUp: !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: !isSelected ? longPress.onTouchEnd : undefined, children: [_jsxs(BaseListingCard.Hero, { aspect: "square", variant: variant, children: [_jsx(TextLink, { href: String(detailHref), className: "absolute inset-0 block", children: thumbItems.length > 0 ? (
92
- // audit-variant-ok: prize-draw item collage — fixed 2x2 grid + gap-0.5 between tiles
93
- _jsx(Div, { layout: "grid", className: "grid-cols-2 grid-rows-2 gap-0.5 h-full w-full bg-[var(--appkit-color-surface-muted)]", children: Array.from({ length: 4 }).map((_, i) => {
91
+ return (_jsxs(BaseListingCard, { isSelected: isSelected, variant: variant, className: className, onMouseDown: !isSelected ? longPress.onMouseDown : undefined, onMouseUp: !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: !isSelected ? longPress.onTouchEnd : undefined, children: [_jsxs(BaseListingCard.Hero, { aspect: "square", variant: variant, children: [_jsx(TextLink, { href: String(detailHref), className: "absolute inset-0 block", children: thumbItems.length > 0 ? (_jsx(Div, { layout: "grid", className: "grid-cols-2 grid-rows-2 gap-0.5 h-full w-full bg-[var(--appkit-color-surface-muted)]", children: Array.from({ length: 4 }).map((_, i) => {
94
92
  const it = thumbItems[i];
95
93
  const img = it?.images?.[0];
96
94
  return (_jsx(Div, { className: "relative overflow-hidden bg-[var(--appkit-color-surface-muted)]", children: img ? (
@@ -18,7 +18,6 @@ import { ShareButton } from "./ShareButton";
18
18
  import { PrizeDrawCollage } from "./PrizeDrawCollage";
19
19
  import { PrizeDrawEntryActions } from "./PrizeDrawEntryActions";
20
20
  import { HistoryTracker } from "../../history/components/HistoryTracker";
21
- // audit-unknown-ok: type-narrowing entry point — accepts any value, narrows by typeof/Array.isArray
22
21
  function toDescriptionHtml(raw) {
23
22
  if (!raw)
24
23
  return "";
@@ -69,7 +68,6 @@ export async function PrizeDrawDetailPageView({ id, initialPrizeDraw, currentUse
69
68
  if (!product) {
70
69
  return (_jsx(Main, { children: _jsx(Section, { padding: "y-5xl", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "center", gap: "md", className: "text-center", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "semibold", color: "primary", children: "Prize Draw Not Found" }), _jsx(Text, { color: "muted", children: "The prize draw you are looking for may have been removed." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "text-sm font-medium text-primary-600 hover:underline", children: "Browse Prize Draws" })] }) }) }) }));
71
70
  }
72
- // audit-unknown-ok: TS structural escape — domain document type lacks index signature
73
71
  const p = product;
74
72
  const currency = p.currency || getDefaultCurrency();
75
73
  const title = String(p.title ?? p.name ?? "Prize Draw");
@@ -88,9 +88,7 @@ export function PrizeDrawItemsEditor({ items, onChange, onUploadImage, onUploadV
88
88
  };
89
89
  return (_jsxs(Stack, { gap: "md", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Heading, { level: 3, children: ["Prize Items (", items.length, ")"] }), _jsxs(Button, { type: "button", variant: "secondary", onClick: addItem, disabled: anyWon || items.length >= MAX_ITEMS, children: ["+ Add prize (", items.length, "/", MAX_ITEMS, ")"] })] }), _jsxs(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: ["Add between ", MIN_ITEMS, " and ", MAX_ITEMS, " prizes. Each entry will reveal exactly one of these. Items marked won during a prior reveal cannot be edited or removed."] }), anyWon ? (_jsxs(Div, { textSize: "sm", className: "border border-error/40", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "default", children: [_jsx(Span, { weight: "bold", children: "Draw locked." }), " At least one prize has been revealed \u2014 this listing can no longer be edited. To run a similar draw, clone it into a new prize-draw listing."] })) : warning ? (_jsx(Div, { className: CLS_WARN_BOX, children: warning })) : null, _jsx(Stack, { gap: "md", children: items.map((it, index) => {
90
90
  const locked = it.isWon || anyWon;
91
- return (_jsxs(Div, { className: `relative border border-[var(--appkit-color-border)] ${locked ? "opacity-60" : ""}`, rounded: "lg", padding: "md", children: [locked ? (
92
- // audit-variant-ok: locked overlay — surface=overlay-xs + bg-black/10 additional tint + pointer-events-none
93
- _jsx(Row, { surface: "overlay-xs", className: "absolute inset-0 z-10 bg-black/10 dark: pointer-events-none", align: "center", justify: "center", rounded: "lg", children: _jsx(Text, { className: CLS_WON_BADGE, children: "Won \u2014 locked" }) })) : null, _jsxs(Row, { justify: "between", align: "center", className: "mb-3", children: [_jsxs(Heading, { level: 4, children: ["Prize #", it.itemNumber] }), _jsxs(Row, { gap: "xs", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(index, -1), disabled: locked || index === 0, "aria-label": "Move up", children: "\u2191" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(index, 1), disabled: locked || index === items.length - 1, "aria-label": "Move down", children: "\u2193" }), _jsx(Button, { type: "button", variant: "danger", size: "sm", onClick: () => removeItem(index), disabled: locked || items.length <= MIN_ITEMS, children: "Remove" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(FormField, { name: `item-${index}-title`, label: "Title", type: "text", value: it.title, onChange: (v) => update(index, { title: v }), disabled: locked, placeholder: "e.g. PSA 9 Charizard Base Set Holo" }), _jsx(FormField, { name: `item-${index}-description`, label: "Description (optional)", type: "textarea", value: it.description ?? "", onChange: (v) => update(index, { description: v }), disabled: locked, placeholder: "What makes this prize special?" }), _jsxs(Row, { gap: "md", children: [_jsx(Div, { className: "flex-1", children: _jsx(FormField, { name: `item-${index}-condition`, label: "Condition", type: "select", value: it.condition, onChange: (v) => update(index, { condition: v }), disabled: locked, options: CONDITION_OPTIONS }) }), _jsx(Div, { className: "flex-1", children: _jsx(FormField, { name: `item-${index}-value`, label: "Estimated value (\u20B9)", type: "number", value: it.estimatedValue != null
91
+ return (_jsxs(Div, { className: `relative border border-[var(--appkit-color-border)] ${locked ? "opacity-60" : ""}`, rounded: "lg", padding: "md", children: [locked ? (_jsx(Row, { surface: "overlay-xs", className: "absolute inset-0 z-10 bg-black/10 dark: pointer-events-none", align: "center", justify: "center", rounded: "lg", children: _jsx(Text, { className: CLS_WON_BADGE, children: "Won \u2014 locked" }) })) : null, _jsxs(Row, { justify: "between", align: "center", className: "mb-3", children: [_jsxs(Heading, { level: 4, children: ["Prize #", it.itemNumber] }), _jsxs(Row, { gap: "xs", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(index, -1), disabled: locked || index === 0, "aria-label": "Move up", children: "\u2191" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(index, 1), disabled: locked || index === items.length - 1, "aria-label": "Move down", children: "\u2193" }), _jsx(Button, { type: "button", variant: "danger", size: "sm", onClick: () => removeItem(index), disabled: locked || items.length <= MIN_ITEMS, children: "Remove" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(FormField, { name: `item-${index}-title`, label: "Title", type: "text", value: it.title, onChange: (v) => update(index, { title: v }), disabled: locked, placeholder: "e.g. PSA 9 Charizard Base Set Holo" }), _jsx(FormField, { name: `item-${index}-description`, label: "Description (optional)", type: "textarea", value: it.description ?? "", onChange: (v) => update(index, { description: v }), disabled: locked, placeholder: "What makes this prize special?" }), _jsxs(Row, { gap: "md", children: [_jsx(Div, { className: "flex-1", children: _jsx(FormField, { name: `item-${index}-condition`, label: "Condition", type: "select", value: it.condition, onChange: (v) => update(index, { condition: v }), disabled: locked, options: CONDITION_OPTIONS }) }), _jsx(Div, { className: "flex-1", children: _jsx(FormField, { name: `item-${index}-value`, label: "Estimated value (\u20B9)", type: "number", value: it.estimatedValue != null
94
92
  ? String(Math.round(it.estimatedValue / 100))
95
93
  : "", onChange: (v) => update(index, {
96
94
  estimatedValue: Math.round((parseFloat(v) || 0) * 100),
@@ -26,7 +26,5 @@ export async function PrizeDrawsSection({ config, }) {
26
26
  catch {
27
27
  draws = [];
28
28
  }
29
- return (_jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "semibold", color: "primary", children: title }), subtitle ? (_jsx(Text, { size: "sm", color: "muted", children: subtitle })) : null] }), draws.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "border-dashed text-center", border: "strong", paddingY: "y-3xl", paddingX: "x-lg", rounded: "2xl", children: [_jsx(Text, { size: "sm", color: "muted", children: "No active prize draws \u2014 new draws are announced regularly." }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: "text-sm font-medium text-primary hover:underline", children: "Browse live auctions \u2192" })] })) : (_jsx(Div, { gap: "3", className: "fluid-grid-card", children: draws.map((draw) => (_jsx(InteractiveProductCard, {
30
- // audit-unknown-ok: TS structural escape — extracted function type
31
- product: draw, href: String(ROUTES.PUBLIC.PRODUCT_DETAIL(draw.slug ?? draw.id ?? "")) }, draw.id))) }))] }) }) }));
29
+ return (_jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "semibold", color: "primary", children: title }), subtitle ? (_jsx(Text, { size: "sm", color: "muted", children: subtitle })) : null] }), draws.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "border-dashed text-center", border: "strong", paddingY: "y-3xl", paddingX: "x-lg", rounded: "2xl", children: [_jsx(Text, { size: "sm", color: "muted", children: "No active prize draws \u2014 new draws are announced regularly." }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: "text-sm font-medium text-primary hover:underline", children: "Browse live auctions \u2192" })] })) : (_jsx(Div, { gap: "3", className: "fluid-grid-card", children: draws.map((draw) => (_jsx(InteractiveProductCard, { product: draw, href: String(ROUTES.PUBLIC.PRODUCT_DETAIL(draw.slug ?? draw.id ?? "")) }, draw.id))) }))] }) }) }));
32
30
  }
@@ -88,7 +88,6 @@ function toReview(doc) {
88
88
  createdAt,
89
89
  };
90
90
  }
91
- // audit-unknown-ok: type-narrowing entry point — accepts any value, narrows by typeof/Array.isArray
92
91
  function toDescriptionHtml(raw) {
93
92
  if (!raw)
94
93
  return "";
@@ -117,7 +116,6 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
117
116
  if (!product) {
118
117
  return (_jsx(Main, { children: _jsx(Section, { padding: "y-5xl", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "center", gap: "md", className: "text-center", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "semibold", color: "primary", children: "Product Not Found" }), _jsx(Text, { color: "muted", children: "The product you are looking for may have been removed or the link is incorrect." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRODUCTS), className: "text-sm font-medium text-primary-600 hover:underline", children: "Browse Products" })] }) }) }) }));
119
118
  }
120
- // audit-unknown-ok: TS structural escape — Record
121
119
  const p = product;
122
120
  const currency = p.currency || getDefaultCurrency();
123
121
  // -- Derived values ---------------------------------------------------------
@@ -212,12 +210,9 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
212
210
  const [reviewDocs, relatedDocs] = await Promise.all([
213
211
  reviewRepository
214
212
  .findApprovedByProduct(product.id)
215
- // audit-unknown-ok: TS structural escape
216
213
  .catch(() => []),
217
214
  category
218
- // audit-unknown-ok: TS structural escape
219
215
  ? productRepository.findByCategory(category).catch(() => [])
220
- // audit-unknown-ok: TS structural escape
221
216
  : Promise.resolve([]),
222
217
  ]);
223
218
  const reviews = reviewDocs.map(toReview);
@@ -236,7 +231,6 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
236
231
  if (r.listingType === "auction" && r.auctionEndDate) {
237
232
  const end = r.auctionEndDate;
238
233
  const endDate = typeof end.toDate === "function"
239
- // audit-unknown-ok: TS structural escape
240
234
  ? end.toDate()
241
235
  : end instanceof Date ? end : new Date(String(end));
242
236
  if (endDate <= _now)
@@ -98,7 +98,5 @@ export function ProductFeatureBadges({ featured, fasterDelivery, ratedSeller, co
98
98
  }
99
99
  if (badges.length === 0)
100
100
  return null;
101
- return (_jsx(Row, { wrap: true, gap: "sm", children: badges.map((badge) => (
102
- // audit-variant-ok: feature badge Span — dynamic badge.bgClass + colorClass + py-1.5 between pad map keys
103
- _jsxs(Span, { layout: "inline-flex", gap: "xs", className: `.5 border py-1.5 ${badge.bgClass} ${badge.colorClass}`, rounded: "lg", padding: "x-sm", size: "xs", weight: "medium", children: [_jsx(Span, { "aria-hidden": "true", children: badge.icon }), badge.label] }, badge.key))) }));
101
+ return (_jsx(Row, { wrap: true, gap: "sm", children: badges.map((badge) => (_jsxs(Span, { layout: "inline-flex", gap: "xs", className: `.5 border py-1.5 ${badge.bgClass} ${badge.colorClass}`, rounded: "lg", padding: "x-sm", size: "xs", weight: "medium", children: [_jsx(Span, { "aria-hidden": "true", children: badge.icon }), badge.label] }, badge.key))) }));
104
102
  }
@@ -26,7 +26,6 @@ function rowClass(checked, cantSelect) {
26
26
  return `${ROW_BASE_CLASS} ${ROW_DISABLED_CLASS}`;
27
27
  return `${ROW_BASE_CLASS} ${ROW_DEFAULT_CLASS}`;
28
28
  }
29
- // audit-unknown-ok: callback entry point — accepts arbitrary payload value
30
29
  function unwrapItems(res) {
31
30
  const body = res?.data ??
32
31
  res;
@@ -68,9 +68,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
68
68
  className,
69
69
  ]
70
70
  .filter(Boolean)
71
- .join(" "), children: [_jsxs(Div, { className: `relative ${__O.hidden} aspect-square`, surface: "subtle", children: [product.mainImage ? (_jsx(MediaImage, { src: product.mainImage, alt: product.title, size: "card", className: "transition-transform duration-500 group-hover:scale-105" })) : (_jsx(Row, { surface: "muted", className: "h-full w-full", align: "center", justify: "center", children: _jsx(Span, { className: "opacity-30", size: "4xl", children: "\uD83D\uDECD\uFE0F" }) })), onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(product.id); }, label: isSelected ? "Deselect" : "Select", position: "top-2 left-2", className: selectionMode || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Stack, { className: `absolute top-2 ${onSelect ? "left-10" : "left-2"}`, gap: "xs", children: !selectionMode && !isSelected && (_jsxs(_Fragment, { children: [discount && (_jsxs(Span, { weight: "bold", className: CLS_BADGE_NEW, children: ["-", discount, "%"] })), typeBadge && (
72
- // audit-variant-ok: listingType badge — typeBadge.cls drives bg/text per listing type; arbitrary text-[10px] + shadow-sm
73
- _jsx(Span, { weight: "bold", className: `text-[10px] shadow-sm ${typeBadge.cls}`, rounded: "full", padding: "pill-xs", children: typeBadge.label })), product.partOfBundleIds && product.partOfBundleIds.length > 0 && (_jsx(Span, { className: CLS_BADGE_SALE, title: product.partOfBundleTitles && product.partOfBundleTitles.length > 0
71
+ .join(" "), children: [_jsxs(Div, { className: `relative ${__O.hidden} aspect-square`, surface: "subtle", children: [product.mainImage ? (_jsx(MediaImage, { src: product.mainImage, alt: product.title, size: "card", className: "transition-transform duration-500 group-hover:scale-105" })) : (_jsx(Row, { surface: "muted", className: "h-full w-full", align: "center", justify: "center", children: _jsx(Span, { className: "opacity-30", size: "4xl", children: "\uD83D\uDECD\uFE0F" }) })), onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(product.id); }, label: isSelected ? "Deselect" : "Select", position: "top-2 left-2", className: selectionMode || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Stack, { className: `absolute top-2 ${onSelect ? "left-10" : "left-2"}`, gap: "xs", children: !selectionMode && !isSelected && (_jsxs(_Fragment, { children: [discount && (_jsxs(Span, { weight: "bold", className: CLS_BADGE_NEW, children: ["-", discount, "%"] })), typeBadge && (_jsx(Span, { weight: "bold", className: `text-[10px] shadow-sm ${typeBadge.cls}`, rounded: "full", padding: "pill-xs", children: typeBadge.label })), product.partOfBundleIds && product.partOfBundleIds.length > 0 && (_jsx(Span, { className: CLS_BADGE_SALE, title: product.partOfBundleTitles && product.partOfBundleTitles.length > 0
74
72
  ? `In bundle: ${product.partOfBundleTitles[0]}`
75
73
  : "In a bundle", children: "Bundled" })), product.groupId && (_jsx(Span, { className: CLS_BADGE_TRENDING, title: product.groupTitle ? `Part of set: ${product.groupTitle}` : "Part of a set", children: product.isGroupParent ? "Set Parent" : "In Set" })), product.sublistingCategoryId && (_jsx(Span, { className: CLS_BADGE_LIMITED, title: "Has variants or sub-listings", children: "Has Variants" }))] })) }), _jsx(BaseListingCard.IconOverlay, { groupIcon: product.groupIcon, sublistingIcon: product.sublistingIcon, position: "bottom-2 right-2" }), onAddToWishlist && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => {
76
74
  e.stopPropagation();
@@ -93,9 +91,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
93
91
  const MAX_CHIPS = 3;
94
92
  const visible = categories.slice(0, MAX_CHIPS);
95
93
  const overflow = Math.max(0, categories.length - MAX_CHIPS);
96
- return (_jsxs(Row, { className: "mt-1", gap: "xs", wrap: true, children: [visible.map((name) => (
97
- // audit-variant-ok: category chip — gap-0.5 below gap.2xs scale + arbitrary text-[10px] + max-w-[100px] truncation
98
- _jsxs(Span, { padding: "pill-2xs", layout: "inline-flex", className: "gap-0.5 text-[10px] truncate max-w-[100px]", rounded: "full", surface: "subtle", color: "muted", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 7a2 2 0 012-2h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7z" }) }), name] }, name))), overflow > 0 && (_jsxs(Span, { padding: "pill-2xs", layout: "inline-flex", weight: "medium", className: "text-[10px]", rounded: "full", surface: "subtle", color: "muted", title: categories.slice(MAX_CHIPS).join(", "), children: ["+", overflow] })), product.brand && (_jsxs(Span, { padding: "pill-2xs", layout: "inline-flex", gap: "2xs", className: "text-[10px] truncate max-w-[90px]", rounded: "full", surface: "subtle", color: "muted", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" }) }), product.brand] }))] }));
94
+ return (_jsxs(Row, { className: "mt-1", gap: "xs", wrap: true, children: [visible.map((name) => (_jsxs(Span, { padding: "pill-2xs", layout: "inline-flex", className: "gap-0.5 text-[10px] truncate max-w-[100px]", rounded: "full", surface: "subtle", color: "muted", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 7a2 2 0 012-2h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7z" }) }), name] }, name))), overflow > 0 && (_jsxs(Span, { padding: "pill-2xs", layout: "inline-flex", weight: "medium", className: "text-[10px]", rounded: "full", surface: "subtle", color: "muted", title: categories.slice(MAX_CHIPS).join(", "), children: ["+", overflow] })), product.brand && (_jsxs(Span, { padding: "pill-2xs", layout: "inline-flex", gap: "2xs", className: "text-[10px] truncate max-w-[90px]", rounded: "full", surface: "subtle", color: "muted", children: [_jsx("svg", { className: "h-2.5 w-2.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" }) }), product.brand] }))] }));
99
95
  })(), (() => {
100
96
  const seller = safeDisplayName(product.storeName, "");
101
97
  return seller ? (_jsxs(Text, { className: "mt-0.5 text-[11px] truncate", color: "faint", children: ["by ", seller] })) : null;
@@ -107,12 +103,8 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
107
103
  return (_jsx(Text, { className: CLS_DISCOUNT_TEXT, children: "Out of stock" }));
108
104
  }
109
105
  const low = stock <= 5;
110
- return (
111
- // audit-variant-ok: stock label conditional warning vs muted-zinc + arbitrary text-[11px]; color depends on runtime stock state
112
- _jsx(Text, { className: `mt-1 text-[11px] ${low ? "text-warning" : "text-zinc-500 dark:text-zinc-400"}`, weight: "medium", children: low ? `Only ${stock} left` : `${stock} in stock` }));
113
- })(), featuresList && product.features && product.features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: product.features, features: featuresList, maxVisible: PRODUCT_FEATURE_CARD_MAX_VISIBLE, className: "mt-2" })), (onAddToCart || onBuyNow) && (
114
- // audit-inline-style-ok: runtime grid template
115
- _jsxs(Div, { layout: "grid", gap: "1", className: "mt-2", style: { gridTemplateColumns: onBuyNow && onAddToCart ? "1fr 1fr" : "1fr" }, children: [onBuyNow && (_jsxs(Button, { gap: "sm", type: "button", variant: "primary", size: "sm", onClick: (e) => {
106
+ return (_jsx(Text, { className: `mt-1 text-[11px] ${low ? "text-warning" : "text-zinc-500 dark:text-zinc-400"}`, weight: "medium", children: low ? `Only ${stock} left` : `${stock} in stock` }));
107
+ })(), featuresList && product.features && product.features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: product.features, features: featuresList, maxVisible: PRODUCT_FEATURE_CARD_MAX_VISIBLE, className: "mt-2" })), (onAddToCart || onBuyNow) && (_jsxs(Div, { layout: "grid", gap: "1", className: "mt-2", style: { gridTemplateColumns: onBuyNow && onAddToCart ? "1fr 1fr" : "1fr" }, children: [onBuyNow && (_jsxs(Button, { gap: "sm", type: "button", variant: "primary", size: "sm", onClick: (e) => {
116
108
  e.stopPropagation();
117
109
  e.preventDefault();
118
110
  onBuyNow(product);
@@ -151,9 +143,7 @@ function ProductListRow({ product, onClick, onAddToWishlist, isWishlisted, }) {
151
143
  return (_jsx(Span, { weight: "semibold", className: CLS_BID_TEXT, children: "Out of stock" }));
152
144
  }
153
145
  const low = stock <= 5;
154
- return (
155
- // audit-variant-ok: list-row stock label — conditional warning vs muted-zinc + arbitrary text-[11px]; color depends on runtime stock state
156
- _jsx(Span, { weight: "medium", className: `text-[11px] ${low
146
+ return (_jsx(Span, { weight: "medium", className: `text-[11px] ${low
157
147
  ? "text-warning"
158
148
  : "text-zinc-400 dark:text-zinc-400"}`, children: low ? `Only ${stock} left` : `${stock} in stock` }));
159
149
  })()] })] }), onAddToWishlist && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => {
@@ -14,7 +14,7 @@ export function ShareButton({ title, text, className = "" }) {
14
14
  // user cancelled or browser blocked — fall through to clipboard
15
15
  }
16
16
  }
17
- navigator.clipboard.writeText(url).catch(() => { }); // audit-silent-catch-ok: clipboard denial is non-fatal; "Copied" toast simply won't show
17
+ navigator.clipboard.writeText(url).catch(() => { });
18
18
  setCopied(true);
19
19
  setTimeout(() => setCopied(false), 2000);
20
20
  };
@@ -23,9 +23,7 @@ function MemberThumb({ member, isCurrent }) {
23
23
  const price = formatCurrency(member.price, member.currency ?? "INR");
24
24
  return (_jsxs(Link, { href: href, "aria-label": member.title, className: "flex flex-col items-center gap-1.5 flex-shrink-0 w-16 group", children: [_jsxs("div", { className: `relative w-14 h-14 rounded-full overflow-hidden border-2 transition-all ${isCurrent
25
25
  ? "border-[var(--appkit-color-primary)] ring-2 ring-[var(--appkit-color-primary)]/30"
26
- : "border-zinc-200 dark:border-zinc-700 group-hover:border-[var(--appkit-color-primary)]"}`, children: [_jsx(MediaImage, { src: image, alt: member.title, size: "card" }), member.isGroupParent && (
27
- // audit-variant-ok: corner badge — absolute-positioned + primary CSS-var bg + arbitrary text-[8px] + rounded-tl (corner-only radius)
28
- _jsx(Span, { color: "inverse", className: "absolute bottom-0 right-0 bg-[var(--appkit-color-primary)] text-[8px] leading-none px-1 py-0.5 rounded-tl", children: "Set" }))] }), _jsx(Text, { className: "text-[10px] leading-tight line-clamp-2 w-full", color: "muted", align: "center", children: member.title }), _jsx(Text, { className: "text-[10px]", color: "primary", weight: "semibold", children: price })] }));
26
+ : "border-zinc-200 dark:border-zinc-700 group-hover:border-[var(--appkit-color-primary)]"}`, children: [_jsx(MediaImage, { src: image, alt: member.title, size: "card" }), member.isGroupParent && (_jsx(Span, { color: "inverse", className: "absolute bottom-0 right-0 bg-[var(--appkit-color-primary)] text-[8px] leading-none px-1 py-0.5 rounded-tl", children: "Set" }))] }), _jsx(Text, { className: "text-[10px] leading-tight line-clamp-2 w-full", color: "muted", align: "center", children: member.title }), _jsx(Text, { className: "text-[10px]", color: "primary", weight: "semibold", children: price })] }));
29
27
  }
30
28
  function GroupTableRow({ member }) {
31
29
  const href = memberHref(member);
@@ -45,7 +43,7 @@ export function ShowGroupSection({ groupId, currentSlug, isParent, groupTitle })
45
43
  fetch(`/api/products/group/${encodeURIComponent(groupId)}`)
46
44
  .then((r) => r.json())
47
45
  .then((res) => setMembers(res.data?.items ?? []))
48
- .catch(() => { }) // audit-silent-catch-ok: group section is supplementary; main PDP renders without it
46
+ .catch(() => { })
49
47
  .finally(() => setLoading(false));
50
48
  }, [groupId]);
51
49
  if (!groupId || loading || members.length <= 1)
@@ -54,9 +52,7 @@ export function ShowGroupSection({ groupId, currentSlug, isParent, groupTitle })
54
52
  const parentLabel = isParent ? `Parts in this group: ${label}` : `Part of: ${label}`;
55
53
  const useDrawer = members.length >= 5;
56
54
  const tableContent = (_jsx(Div, { className: `${__O.xAuto}`, children: _jsxs(Table, { className: "text-left min-w-[400px]", children: [_jsx(Thead, { children: _jsxs(Tr, { border: "default", children: [_jsx(Th, { className: "pb-2 pr-3", color: "muted", size: "xs", weight: "semibold", children: "Image" }), _jsx(Th, { className: "pb-2 pr-3", color: "muted", size: "xs", weight: "semibold", children: "Name" }), _jsx(Th, { className: "pb-2 pr-3", color: "muted", size: "xs", weight: "semibold", children: "Price" }), _jsx(Th, { className: "pb-2 pr-3", color: "muted", size: "xs", weight: "semibold", children: "Condition" }), _jsx(Th, { className: "pb-2", color: "muted", size: "xs", weight: "semibold" })] }) }), _jsx(Tbody, { children: members.map((m) => _jsx(GroupTableRow, { member: m }, m.id)) })] }) }));
57
- return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: `${__O.hidden}`, surface: "muted", rounded: "xl", border: "default", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx(Span, { size: "xs", className: "mr-1", color: "faint", children: open ? "â–¼" : "â–¶" }), _jsx(Text, { size: "sm", weight: "medium", color: "primary", children: parentLabel }), _jsx(Span, { size: "xs", className: "ml-1", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: members.length })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); setShowAll(true); }, className: "text-xs text-[var(--appkit-color-primary)] hover:underline ml-3 flex-shrink-0", children: "View whole group \u00E2\u2020\u2019" })] }), open && (
58
- // audit-variant-ok: pb-4 pt-1 are asymmetric single-axis paddings; no t/b combo token in PADDING_MAP
59
- _jsx(Div, { className: `pb-4 pt-1 ${__O.xAuto}`, padding: "x-md", children: _jsx(Row, { gap: "3", className: "min-w-0", children: [...members]
55
+ return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: `${__O.hidden}`, surface: "muted", rounded: "xl", border: "default", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx(Span, { size: "xs", className: "mr-1", color: "faint", children: open ? "â–¼" : "â–¶" }), _jsx(Text, { size: "sm", weight: "medium", color: "primary", children: parentLabel }), _jsx(Span, { size: "xs", className: "ml-1", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: members.length })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => { e.stopPropagation(); setShowAll(true); }, className: "text-xs text-[var(--appkit-color-primary)] hover:underline ml-3 flex-shrink-0", children: "View whole group \u00E2\u2020\u2019" })] }), open && (_jsx(Div, { className: `pb-4 pt-1 ${__O.xAuto}`, padding: "x-md", children: _jsx(Row, { gap: "3", className: "min-w-0", children: [...members]
60
56
  .sort((a, b) => (b.isGroupParent ? 1 : 0) - (a.isGroupParent ? 1 : 0))
61
57
  .map((m) => (_jsx(MemberThumb, { member: m, isCurrent: m.slug === currentSlug || m.id === currentSlug }, m.id))) }) }))] }), useDrawer ? (_jsx(SideDrawer, { isOpen: showAll, onClose: () => setShowAll(false), title: label, children: tableContent })) : (_jsx(Modal, { open: showAll, onClose: () => setShowAll(false), title: label, children: tableContent }))] }));
62
58
  }
@@ -43,7 +43,7 @@ export function SublistingCarouselSection({ sublistingCategoryId, currentListing
43
43
  setCategory(res.data?.category ?? null);
44
44
  setListings(res.data?.listings ?? []);
45
45
  })
46
- .catch(() => { }) // audit-silent-catch-ok: sublisting carousel is supplementary; main PDP renders without it
46
+ .catch(() => { })
47
47
  .finally(() => setLoading(false));
48
48
  }, [sublistingCategoryId]);
49
49
  if (!sublistingCategoryId || loading || (!category && !loading))
@@ -54,7 +54,5 @@ export function SublistingCarouselSection({ sublistingCategoryId, currentListing
54
54
  if (others.length === 0)
55
55
  return null;
56
56
  const label = category?.name ?? "More listings like this";
57
- return (_jsxs(Div, { className: `${__O.hidden}`, surface: "muted", rounded: "xl", border: "default", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx(Span, { size: "xs", className: "mr-1", color: "faint", children: open ? "â–¼" : "â–¶" }), _jsxs(Text, { size: "sm", weight: "medium", color: "primary", children: ["More listings like this:", " ", _jsx(Span, { className: "text-[var(--appkit-color-primary)]", children: label })] }), _jsx(Span, { size: "xs", className: "ml-1", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: listings.length })] }), category && (_jsx(Link, { href: String(ROUTES.PUBLIC.SUBLISTING_CATEGORY(category.slug)), onClick: (e) => e.stopPropagation(), className: "text-xs text-[var(--appkit-color-primary)] hover:underline ml-3 flex-shrink-0", children: "View all \u00E2\u2020\u2019" }))] }), open && (
58
- // audit-variant-ok: pb-4 pt-1 are asymmetric single-axis paddings; no t/b combo token in PADDING_MAP
59
- _jsx(Div, { className: `pb-4 pt-1 ${__O.xAuto}`, padding: "x-md", children: _jsx(Row, { gap: "3", className: "min-w-0", children: listings.map((listing) => (_jsx(ListingThumb, { listing: listing, isCurrent: listing.id === currentListingId }, listing.id))) }) }))] }));
57
+ return (_jsxs(Div, { className: `${__O.hidden}`, surface: "muted", rounded: "xl", border: "default", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx(Span, { size: "xs", className: "mr-1", color: "faint", children: open ? "â–¼" : "â–¶" }), _jsxs(Text, { size: "sm", weight: "medium", color: "primary", children: ["More listings like this:", " ", _jsx(Span, { className: "text-[var(--appkit-color-primary)]", children: label })] }), _jsx(Span, { size: "xs", className: "ml-1", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: listings.length })] }), category && (_jsx(Link, { href: String(ROUTES.PUBLIC.SUBLISTING_CATEGORY(category.slug)), onClick: (e) => e.stopPropagation(), className: "text-xs text-[var(--appkit-color-primary)] hover:underline ml-3 flex-shrink-0", children: "View all \u00E2\u2020\u2019" }))] }), open && (_jsx(Div, { className: `pb-4 pt-1 ${__O.xAuto}`, padding: "x-md", children: _jsx(Row, { gap: "3", className: "min-w-0", children: listings.map((listing) => (_jsx(ListingThumb, { listing: listing, isCurrent: listing.id === currentListingId }, listing.id))) }) }))] }));
60
58
  }
@@ -12,7 +12,6 @@ function slugify(value) {
12
12
  .replace(/[^a-z0-9]+/g, "-")
13
13
  .replace(/^-+|-+$/g, "");
14
14
  }
15
- // audit-unknown-ok: error-handler entry point — accepts thrown values of any shape
16
15
  function failureMessage(prefix, error) {
17
16
  return `${prefix}: ${error instanceof Error ? error.message : "Unknown error"}`;
18
17
  }
@@ -80,7 +80,6 @@ export class ProductRepository extends BaseRepository {
80
80
  if (!doc.categorySlugs || doc.categorySlugs.length === 0) {
81
81
  doc.categorySlugs = doc.category ? [doc.category] : [];
82
82
  }
83
- // audit-unknown-ok: TS structural escape — generic param
84
83
  return doc;
85
84
  }
86
85
  async update(id, data) {
@@ -15,7 +15,6 @@ const TYPE_COLORS = {
15
15
  function pick(obj, ...keys) {
16
16
  for (const k of keys) {
17
17
  const parts = k.split(".");
18
- // audit-unknown-ok: Coupon shape resolver — accepts flat or nested input
19
18
  let cur = obj;
20
19
  for (const p of parts) {
21
20
  if (cur && typeof cur === "object")
@@ -105,7 +104,7 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
105
104
  const handleCopy = () => {
106
105
  if (!n.code)
107
106
  return;
108
- navigator.clipboard.writeText(n.code).catch(() => { }); // audit-silent-catch-ok: clipboard denial is non-fatal; "Copied" UI simply won't toggle
107
+ navigator.clipboard.writeText(n.code).catch(() => { });
109
108
  setCopied(true);
110
109
  onCopy?.(n.code);
111
110
  setTimeout(() => setCopied(false), 2000);
@@ -160,9 +159,7 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
160
159
  setBusy(null);
161
160
  }
162
161
  };
163
- return (_jsxs(Stack, { className: `group relative h-full border-2 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, rounded: "xl", padding: "md", 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(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Badge, { variant: n.isActive ? "active" : "inactive", size: "xs", className: "text-[10px] uppercase tracking-wide", children: n.isActive ? labels.active : labels.inactive }), n.scope && (
164
- // audit-variant-ok: scope chip — translucent bg-zinc-200/70 + text-[10px] under-10
165
- _jsx(Span, { layout: "inline-flex", weight: "semibold", className: "bg-zinc-200/70 text-[10px] tracking-wide dark:bg-zinc-700/60", rounded: "full", padding: "pill-xs", color: "primary", transform: "uppercase", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "font-extrabold tracking-tight leading-none", size: "2xl", children: discountLabel }), n.name && (_jsx(Text, { className: "mt-0.5 opacity-80", size: "sm", weight: "medium", children: n.name }))] }), n.description && (_jsx(Text, { className: "opacity-60 mb-3", size: "xs", children: n.description })), _jsxs(Row, { className: `border border-dashed ${colors.code}`, align: "center", gap: "sm", rounded: "lg", padding: "inlineSm", children: [_jsx(Span, { size: "sm", weight: "bold", className: "flex-1 font-mono tracking-widest select-all", transform: "uppercase", children: n.code || "—" }), n.code && (_jsx("button", { type: "button", onClick: handleCopy, className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-semibold transition-all hover:opacity-80 active:scale-95 bg-white/60 dark:bg-black/20 border border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx(Div, { className: "mt-2", children: _jsx("button", { type: "button", onClick: handleClaim, disabled: claiming, className: "w-full rounded-md px-3 py-1.5 text-xs font-semibold transition-all active:scale-95 bg-[var(--appkit-color-primary-700)] text-[var(--appkit-color-text-on-primary)] hover:bg-[var(--appkit-color-primary-800)] disabled:opacity-50", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { textSize: "xs", wrap: true, gap: "sm", className: "opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", (n.minOrderAmount / 100).toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", justify: "end", className: "mt-auto", padding: "t-sm", children: [onEdit && (_jsx("button", { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 hover:text-zinc-800 dark:hover:text-zinc-200 transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx("button", { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 transition-colors disabled:opacity-50", children: n.isActive
162
+ return (_jsxs(Stack, { className: `group relative h-full border-2 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, rounded: "xl", padding: "md", 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(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Badge, { variant: n.isActive ? "active" : "inactive", size: "xs", className: "text-[10px] uppercase tracking-wide", children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { layout: "inline-flex", weight: "semibold", className: "bg-zinc-200/70 text-[10px] tracking-wide dark:bg-zinc-700/60", rounded: "full", padding: "pill-xs", color: "primary", transform: "uppercase", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "font-extrabold tracking-tight leading-none", size: "2xl", children: discountLabel }), n.name && (_jsx(Text, { className: "mt-0.5 opacity-80", size: "sm", weight: "medium", children: n.name }))] }), n.description && (_jsx(Text, { className: "opacity-60 mb-3", size: "xs", children: n.description })), _jsxs(Row, { className: `border border-dashed ${colors.code}`, align: "center", gap: "sm", rounded: "lg", padding: "inlineSm", children: [_jsx(Span, { size: "sm", weight: "bold", className: "flex-1 font-mono tracking-widest select-all", transform: "uppercase", children: n.code || "—" }), n.code && (_jsx("button", { type: "button", onClick: handleCopy, className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-semibold transition-all hover:opacity-80 active:scale-95 bg-white/60 dark:bg-black/20 border border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx(Div, { className: "mt-2", children: _jsx("button", { type: "button", onClick: handleClaim, disabled: claiming, className: "w-full rounded-md px-3 py-1.5 text-xs font-semibold transition-all active:scale-95 bg-[var(--appkit-color-primary-700)] text-[var(--appkit-color-text-on-primary)] hover:bg-[var(--appkit-color-primary-800)] disabled:opacity-50", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { textSize: "xs", wrap: true, gap: "sm", className: "opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", (n.minOrderAmount / 100).toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", justify: "end", className: "mt-auto", padding: "t-sm", children: [onEdit && (_jsx("button", { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 hover:text-zinc-800 dark:hover:text-zinc-200 transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx("button", { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 transition-colors disabled:opacity-50", children: n.isActive
166
163
  ? _jsx(ToggleRight, { className: CLS_TOGGLE_ON })
167
164
  : _jsx(ToggleLeft, { className: "h-4 w-4" }) })), onDelete && (_jsx("button", { type: "button", onClick: () => setDeleteConfirmOpen(true), disabled: busy === "delete", title: labels.delete, "aria-label": labels.delete, className: CLS_DELETE_BTN, children: _jsx(Trash2, { className: "h-4 w-4" }) }))] })), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Coupon", message: labels.deleteConfirm, onConfirm: handleDeleteConfirmed, onClose: () => setDeleteConfirmOpen(false), isDeleting: busy === "delete" }))] }));
168
165
  }
@@ -474,7 +474,6 @@ export class CouponsRepository extends BaseRepository {
474
474
  * Cloud Functions: stage coupon deactivation into a caller-owned WriteBatch.
475
475
  */
476
476
  deactivateInBatch(batch, ref) {
477
- // audit-unknown-ok: TS structural escape — Firebase SDK type
478
477
  batch.update(ref, {
479
478
  [COUPON_FIELDS.VALIDITY.IS_ACTIVE]: false,
480
479
  updatedAt: serverTimestamp(),
@@ -167,7 +167,6 @@ export const POST = createRouteHandler({
167
167
  status: "pending",
168
168
  createdAt: now,
169
169
  updatedAt: now,
170
- // audit-unknown-ok: TS structural escape — Review
171
170
  });
172
171
  return NextResponse.json({ success: true, data: created }, { status: 201 });
173
172
  },
@@ -89,19 +89,9 @@ export function ReviewDetailShell({ review, storeHref }) {
89
89
  ? String(ROUTES.PUBLIC.PROFILE(reviewerProfileId))
90
90
  : null;
91
91
  const currentImage = lightboxIdx !== null ? images[lightboxIdx] : null;
92
- return (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "default", className: "border-b border-neutral-200 pt-10", padding: "b-xl", children: _jsxs(Div, { className: "mx-auto max-w-3xl", padding: "x-md", children: [_jsxs(Row, { gap: "sm", className: "mb-4", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs(Span, { color: "inverse", weight: "bold", className: "text-neutral-900 dark:text-neutral-100 dark:", size: "2xl", children: [review.rating, ".0"] }), review.verified && (_jsx(Span, { layout: "inline-flex", gap: "xs", color: "success", surface: "success-surface", size: "xs", weight: "semibold", rounded: "full", padding: "pill-md", children: "\u2713 Verified Purchase" })), review.featured && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_RATING_PILL, children: "\u2605 Featured" }))] }), review.title && (_jsx(Heading, { color: "inverse", level: 1, className: "text-neutral-900 dark:text-neutral-100 dark: mb-4 leading-snug", size: "2xl", weight: "bold", children: review.title })), _jsxs(Row, { gap: "sm", children: [review.userAvatar ? (_jsx(Div, { role: "img", "aria-label": displayName, className: "h-11 w-11 flex-shrink-0 bg-center bg-cover ring-2 ring-white dark:ring-zinc-800", rounded: "full",
93
- // audit-inline-style-ok: dynamic image URL
94
- style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx(Row, { textWeight: "bold", textSize: "base", centered: true, className: "h-11 w-11 flex-shrink-0 bg-primary/10 text-primary ring-2 ring-white dark:ring-zinc-800", rounded: "full", children: initials })), _jsxs(Div, { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-neutral-100 dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx(Span, { color: "inverse", size: "sm", weight: "semibold", className: "text-neutral-900 dark:text-neutral-100 dark:", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx(Text, { size: "xs", color: "muted", className: "mt-0.5", children: date }))] })] })] }) }), _jsxs(Stack, { gap: "xl", className: "mx-auto max-w-3xl", paddingY: "y-xl", paddingX: "x-md", children: [review.comment && (_jsx(Section, { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs(Section, { children: [_jsxs(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: ["Photos (", images.length, ")"] }), _jsx(Grid, { gap: "xs", className: "grid-cols-3 sm:grid-cols-4", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx(Div, { className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105",
95
- // audit-inline-style-ok: dynamic image URL
96
- style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }), _jsx(Row, { centered: true, className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity bg-black/30", children: _jsx(Span, { color: "inverse", size: "xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: "Video" }), _jsx(Div, { className: `${__O.hidden} border border-neutral-200 dark:border-zinc-700 bg-black aspect-video`, rounded: "xl", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs(Section, { className: "flex items-center gap-4 border-t border-neutral-100", padding: "y-md", children: [_jsx(Div, { textSize: "sm", className: "text-neutral-500 dark:text-neutral-400", children: helpfulCount > 0 && (_jsxs(Span, { children: [_jsx(Span, { color: "inverse", weight: "bold", className: "text-neutral-900 dark:text-neutral-100 dark:", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
92
+ return (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "default", className: "border-b border-neutral-200 pt-10", padding: "b-xl", children: _jsxs(Div, { className: "mx-auto max-w-3xl", padding: "x-md", children: [_jsxs(Row, { gap: "sm", className: "mb-4", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs(Span, { color: "inverse", weight: "bold", className: "text-neutral-900 dark:text-neutral-100 dark:", size: "2xl", children: [review.rating, ".0"] }), review.verified && (_jsx(Span, { layout: "inline-flex", gap: "xs", color: "success", surface: "success-surface", size: "xs", weight: "semibold", rounded: "full", padding: "pill-md", children: "\u2713 Verified Purchase" })), review.featured && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_RATING_PILL, children: "\u2605 Featured" }))] }), review.title && (_jsx(Heading, { color: "inverse", level: 1, className: "text-neutral-900 dark:text-neutral-100 dark: mb-4 leading-snug", size: "2xl", weight: "bold", children: review.title })), _jsxs(Row, { gap: "sm", children: [review.userAvatar ? (_jsx(Div, { role: "img", "aria-label": displayName, className: "h-11 w-11 flex-shrink-0 bg-center bg-cover ring-2 ring-white dark:ring-zinc-800", rounded: "full", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx(Row, { textWeight: "bold", textSize: "base", centered: true, className: "h-11 w-11 flex-shrink-0 bg-primary/10 text-primary ring-2 ring-white dark:ring-zinc-800", rounded: "full", children: initials })), _jsxs(Div, { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-neutral-100 dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx(Span, { color: "inverse", size: "sm", weight: "semibold", className: "text-neutral-900 dark:text-neutral-100 dark:", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx(Text, { size: "xs", color: "muted", className: "mt-0.5", children: date }))] })] })] }) }), _jsxs(Stack, { gap: "xl", className: "mx-auto max-w-3xl", paddingY: "y-xl", paddingX: "x-md", children: [review.comment && (_jsx(Section, { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs(Section, { children: [_jsxs(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: ["Photos (", images.length, ")"] }), _jsx(Grid, { gap: "xs", className: "grid-cols-3 sm:grid-cols-4", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx(Div, { className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }), _jsx(Row, { centered: true, className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity bg-black/30", children: _jsx(Span, { color: "inverse", size: "xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: "Video" }), _jsx(Div, { className: `${__O.hidden} border border-neutral-200 dark:border-zinc-700 bg-black aspect-video`, rounded: "xl", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs(Section, { className: "flex items-center gap-4 border-t border-neutral-100", padding: "y-md", children: [_jsx(Div, { textSize: "sm", className: "text-neutral-500 dark:text-neutral-400", children: helpfulCount > 0 && (_jsxs(Span, { children: [_jsx(Span, { color: "inverse", weight: "bold", className: "text-neutral-900 dark:text-neutral-100 dark:", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
97
93
  ? CLS_HELPFUL_ACTIVE
98
- : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx(Span, { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs(Section, { className: "grid gap-3 sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_ORANGE, children: "\uD83D\uDCE6" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Product" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_BLUE, children: "\uD83C\uDFEA" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Seller" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_PURPLE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Reviewer" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: displayName })] })] })) : (
99
- // audit-variant-ok: anonymous reviewer fallback Row — explicit neutral/zinc border tokens + p-4 padding constant
100
- _jsxs(Row, { surface: "default", gap: "sm", className: `border border-neutral-200 dark:border-zinc-700 ${__P.p4}`, rounded: "xl", children: [_jsx(Span, { size: "xl", className: CLS_ICON_PURPLE_BARE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Span, { size: "xs", className: "block mb-0.5", color: "faint", children: "Reviewer" }), _jsx(Span, { color: "inverse", size: "sm", weight: "medium", className: "block text-neutral-900 dark:text-neutral-100 dark: truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (
101
- // audit-variant-ok: lightbox modal scrim — fixed inset-0 + bg-black/95 (denser than overlay-xl preset); z-50 for full-screen overlay
102
- _jsxs(Row, { centered: true, className: "fixed inset-0 z-50 bg-black/95", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs(Div, { textSize: "sm", className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx(Row, { centered: true, className: "max-h-[85vh] max-w-[85vw]", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx(Row, { justify: "center", gap: "xs", className: "absolute bottom-4 left-0 right-0", padding: "x-md", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md bg-center bg-cover border-2 transition-all ${i === lightboxIdx
94
+ : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx(Span, { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs(Section, { className: "grid gap-3 sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_ORANGE, children: "\uD83D\uDCE6" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Product" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_BLUE, children: "\uD83C\uDFEA" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Seller" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_PURPLE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Reviewer" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: displayName })] })] })) : (_jsxs(Row, { surface: "default", gap: "sm", className: `border border-neutral-200 dark:border-zinc-700 ${__P.p4}`, rounded: "xl", children: [_jsx(Span, { size: "xl", className: CLS_ICON_PURPLE_BARE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Span, { size: "xs", className: "block mb-0.5", color: "faint", children: "Reviewer" }), _jsx(Span, { color: "inverse", size: "sm", weight: "medium", className: "block text-neutral-900 dark:text-neutral-100 dark: truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (_jsxs(Row, { centered: true, className: "fixed inset-0 z-50 bg-black/95", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs(Div, { textSize: "sm", className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx(Row, { centered: true, className: "max-h-[85vh] max-w-[85vw]", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx(Row, { justify: "center", gap: "xs", className: "absolute bottom-4 left-0 right-0", padding: "x-md", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md bg-center bg-cover border-2 transition-all ${i === lightboxIdx
103
95
  ? "border-white scale-110"
104
- : "border-transparent opacity-60 hover:opacity-100"}`,
105
- // audit-inline-style-ok: dynamic image URL
106
- style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }, i))) }))] }))] }));
96
+ : "border-transparent opacity-60 hover:opacity-100"}`, style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }, i))) }))] }))] }));
107
97
  }
@@ -23,11 +23,7 @@ export function ViewReviewModal({ review, isOpen, onClose, }) {
23
23
  day: "numeric",
24
24
  })
25
25
  : "";
26
- return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: "Review Details", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { gap: "3", children: [review.userAvatar ? (_jsx(Div, { role: "img", "aria-label": displayName, className: "h-10 w-10 flex-shrink-0 bg-center bg-cover", rounded: "full",
27
- // audit-inline-style-ok: dynamic image URL
28
- style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-10 w-10 flex-shrink-0 bg-neutral-200 text-neutral-600 dark:text-neutral-400", align: "center", justify: "center", rounded: "full", children: displayName.charAt(0).toUpperCase() })), _jsxs(Div, { children: [_jsxs(Row, { gap: "sm", children: [_jsx(Text, { color: "inverse", className: "text-neutral-900 dark:text-neutral-100 dark:", weight: "medium", children: displayName }), review.verified && (_jsx(Text, { className: THEMED_TEXT_SUCCESS, size: "xs", children: "\u2713 Verified purchase" }))] }), _jsxs(Row, { className: "mt-0.5", gap: "sm", children: [_jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }), date && (_jsx(Text, { size: "xs", color: "faint", children: date }))] })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "text-neutral-900 dark:text-neutral-100 dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-neutral-600 dark:text-zinc-400" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", children: review.images.map((img, i) => (_jsx(IconButton, { "aria-label": `View image ${i + 1}`, onClick: () => setLightboxIdx(i), variant: "ghost", className: `h-20 w-20 rounded-lg border bg-center bg-cover transition hover:opacity-80 p-0 ${lightboxIdx === i ? "ring-2 ring-primary-500" : "border-neutral-100 dark:border-zinc-700"}`,
29
- // audit-inline-style-ok: dynamic CSS
30
- style: {
26
+ return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: "Review Details", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { gap: "3", children: [review.userAvatar ? (_jsx(Div, { role: "img", "aria-label": displayName, className: "h-10 w-10 flex-shrink-0 bg-center bg-cover", rounded: "full", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-10 w-10 flex-shrink-0 bg-neutral-200 text-neutral-600 dark:text-neutral-400", align: "center", justify: "center", rounded: "full", children: displayName.charAt(0).toUpperCase() })), _jsxs(Div, { children: [_jsxs(Row, { gap: "sm", children: [_jsx(Text, { color: "inverse", className: "text-neutral-900 dark:text-neutral-100 dark:", weight: "medium", children: displayName }), review.verified && (_jsx(Text, { className: THEMED_TEXT_SUCCESS, size: "xs", children: "\u2713 Verified purchase" }))] }), _jsxs(Row, { className: "mt-0.5", gap: "sm", children: [_jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }), date && (_jsx(Text, { size: "xs", color: "faint", children: date }))] })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "text-neutral-900 dark:text-neutral-100 dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-neutral-600 dark:text-zinc-400" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", children: review.images.map((img, i) => (_jsx(IconButton, { "aria-label": `View image ${i + 1}`, onClick: () => setLightboxIdx(i), variant: "ghost", className: `h-20 w-20 rounded-lg border bg-center bg-cover transition hover:opacity-80 p-0 ${lightboxIdx === i ? "ring-2 ring-primary-500" : "border-neutral-100 dark:border-zinc-700"}`, style: {
31
27
  backgroundImage: `url(${img.thumbnailUrl ?? img.url})`,
32
28
  }, icon: _jsx(Div, {}) }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { size: "xs", color: "faint", children: [review.helpfulCount, " people found this helpful"] })), _jsx(Row, { justify: "end", padding: "t-xs", children: _jsx(Button, { variant: "ghost", onClick: onClose, children: "Close" }) })] }) }));
33
29
  }
@@ -13,13 +13,9 @@ const CLS_BAR = "h-full rounded-full bg-warning-surface transition-all duration-
13
13
  */
14
14
  export function ReviewSummary({ averageRating, totalReviews, distribution, className = "", }) {
15
15
  const stars = [5, 4, 3, 2, 1];
16
- return (
17
- // audit-variant-ok: review summary Stack — base flex-col + sm:flex-row + sm:gap-8 responsive direction
18
- _jsxs(Stack, { align: "center", className: `sm:flex-row sm: sm:gap-8 ${className}`, gap: "md", children: [_jsxs(Stack, { className: "sm:items-start", align: "center", gap: "xs", children: [_jsx(Span, { color: "inverse", weight: "bold", className: "leading-none text-neutral-900 dark:text-neutral-100 dark:", size: "5xl", children: averageRating.toFixed(1) }), _jsx(StarRating, { value: averageRating, size: "md", readOnly: true }), _jsxs(Text, { size: "sm", className: "text-neutral-500 dark:text-neutral-400", children: [totalReviews.toLocaleString(), " review", totalReviews !== 1 ? "s" : ""] })] }), _jsx(Stack, { className: "flex-1", gap: "sm", children: stars.map((star) => {
16
+ return (_jsxs(Stack, { align: "center", className: `sm:flex-row sm: sm:gap-8 ${className}`, gap: "md", children: [_jsxs(Stack, { className: "sm:items-start", align: "center", gap: "xs", children: [_jsx(Span, { color: "inverse", weight: "bold", className: "leading-none text-neutral-900 dark:text-neutral-100 dark:", size: "5xl", children: averageRating.toFixed(1) }), _jsx(StarRating, { value: averageRating, size: "md", readOnly: true }), _jsxs(Text, { size: "sm", className: "text-neutral-500 dark:text-neutral-400", children: [totalReviews.toLocaleString(), " review", totalReviews !== 1 ? "s" : ""] })] }), _jsx(Stack, { className: "flex-1", gap: "sm", children: stars.map((star) => {
19
17
  const count = distribution[star] ?? 0;
20
18
  const pct = totalReviews > 0 ? Math.round((count / totalReviews) * 100) : 0;
21
- return (_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "xs", weight: "medium", className: "w-4 text-neutral-600 dark:text-neutral-400 tabular-nums", align: "end", children: star }), _jsx(Span, { size: "xs", className: CLS_STAR, children: "\u2605" }), _jsx(Div, { className: "flex-1 h-2 bg-neutral-100 dark:bg-neutral-800 overflow-hidden", rounded: "full", role: "progressbar", "aria-valuenow": pct, "aria-valuemin": 0, "aria-valuemax": 100, "aria-label": `${star} star: ${pct}%`, children: _jsx(Div, { className: CLS_BAR,
22
- // audit-inline-style-ok: computed percentage
23
- style: { width: `${pct}%` } }) }), _jsxs(Span, { size: "xs", className: "w-8 tabular-nums", color: "faint", align: "end", children: [pct, "%"] })] }, star));
19
+ return (_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "xs", weight: "medium", className: "w-4 text-neutral-600 dark:text-neutral-400 tabular-nums", align: "end", children: star }), _jsx(Span, { size: "xs", className: CLS_STAR, children: "\u2605" }), _jsx(Div, { className: "flex-1 h-2 bg-neutral-100 dark:bg-neutral-800 overflow-hidden", rounded: "full", role: "progressbar", "aria-valuenow": pct, "aria-valuemin": 0, "aria-valuemax": 100, "aria-label": `${star} star: ${pct}%`, children: _jsx(Div, { className: CLS_BAR, style: { width: `${pct}%` } }) }), _jsxs(Span, { size: "xs", className: "w-8 tabular-nums", color: "faint", align: "end", children: [pct, "%"] })] }, star));
24
20
  }) })] }));
25
21
  }
@@ -63,7 +63,6 @@ export function ReviewsIndexListing({ initialData, variant = "public", }) {
63
63
  buildSieveParams: () => "",
64
64
  buildSearchParams: () => "",
65
65
  params: new URLSearchParams(),
66
- // audit-unknown-ok: TS structural escape — table-state type
67
66
  }), [pendingFilters]);
68
67
  const openFilters = useCallback(() => {
69
68
  setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
@@ -27,13 +27,7 @@ export function ReviewCard({ review, context = "general", className = "" }) {
27
27
  const showProductLink = context !== "listing" && !!productHref;
28
28
  const showProfileLink = !!profileHref;
29
29
  const hasFooter = showStoreLink || showProductLink || showProfileLink;
30
- return (
31
- // audit-variant-ok: review card Stack — h-full + hover-shadow-md transition + border-neutral-200 over surface=default
32
- _jsxs(Stack, { padding: "5", className: `group h-full border border-neutral-200 transition-shadow hover:shadow-md ${className}`, rounded: "xl", surface: "default", children: [_jsxs(Link, { href: reviewHref, className: "flex flex-col flex-1 min-h-0", children: [_jsxs(Row, { align: "start", gap: "3", children: [review.userAvatar ? (_jsx(Div, { role: "img", "aria-label": displayName, className: "h-9 w-9 flex-shrink-0 bg-center bg-cover", rounded: "full",
33
- // audit-inline-style-ok: dynamic image URL
34
- style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-9 w-9 flex-shrink-0 bg-neutral-200 text-neutral-600 dark:text-neutral-400", align: "center", justify: "center", rounded: "full", children: initials })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Span, { color: "inverse", weight: "medium", className: "text-neutral-900 dark:text-neutral-100 dark:", children: displayName }), review.verified && (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", rounded: "full", padding: "pill-xs", children: "Verified" })), date && (_jsx(Span, { size: "xs", color: "muted", children: date }))] }), _jsx(Div, { className: "mt-1", children: _jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }) })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "mt-3 text-neutral-900 dark:text-neutral-100 dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "mt-2 text-sm leading-relaxed text-neutral-600 dark:text-zinc-400" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-3", children: review.images.map((img, i) => (_jsx(Div, { role: "img", "aria-label": `Review image ${i + 1}`, className: "h-16 w-16 bg-center bg-cover border border-neutral-100", rounded: "lg",
35
- // audit-inline-style-ok: dynamic image URL
36
- style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [review.helpfulCount, " found this helpful"] }))] }), hasFooter && (_jsxs(Stack, { gap: "xs", className: "mt-3 border-t border-neutral-100", padding: "t-sm", children: [showStoreLink && (_jsxs(Link, { href: String(ROUTES.PUBLIC.STORE_DETAIL(review.storeSlug)), className: "flex items-center gap-1.5 text-xs font-medium text-primary hover:underline", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83C\uDFEA" }), _jsx(Span, { truncate: true, children: review.storeName })] })), showProductLink && (_jsxs(Link, { href: productHref, className: "flex items-center gap-1.5 text-xs font-medium text-neutral-500 dark:text-zinc-400 hover:text-neutral-700 dark:hover:text-zinc-200", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDCE6" }), _jsx(Span, { truncate: true, children: review.productTitle ?? "View Product" }), _jsx(Span, { "aria-hidden": "true", className: "ml-auto text-primary group-hover:translate-x-0.5 transition-transform", children: "\u2192" })] })), showProfileLink && (_jsxs(Link, { href: profileHref, className: "flex items-center gap-1.5 text-xs font-medium text-neutral-500 dark:text-zinc-400 hover:text-neutral-700 dark:hover:text-zinc-200", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDC64" }), _jsx(Span, { truncate: true, children: displayName })] }))] }))] }));
30
+ return (_jsxs(Stack, { padding: "5", className: `group h-full border border-neutral-200 transition-shadow hover:shadow-md ${className}`, rounded: "xl", surface: "default", children: [_jsxs(Link, { href: reviewHref, className: "flex flex-col flex-1 min-h-0", children: [_jsxs(Row, { align: "start", gap: "3", children: [review.userAvatar ? (_jsx(Div, { role: "img", "aria-label": displayName, className: "h-9 w-9 flex-shrink-0 bg-center bg-cover", rounded: "full", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-9 w-9 flex-shrink-0 bg-neutral-200 text-neutral-600 dark:text-neutral-400", align: "center", justify: "center", rounded: "full", children: initials })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Span, { color: "inverse", weight: "medium", className: "text-neutral-900 dark:text-neutral-100 dark:", children: displayName }), review.verified && (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", rounded: "full", padding: "pill-xs", children: "Verified" })), date && (_jsx(Span, { size: "xs", color: "muted", children: date }))] }), _jsx(Div, { className: "mt-1", children: _jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }) })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "mt-3 text-neutral-900 dark:text-neutral-100 dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "mt-2 text-sm leading-relaxed text-neutral-600 dark:text-zinc-400" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-3", children: review.images.map((img, i) => (_jsx(Div, { role: "img", "aria-label": `Review image ${i + 1}`, className: "h-16 w-16 bg-center bg-cover border border-neutral-100", rounded: "lg", style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [review.helpfulCount, " found this helpful"] }))] }), hasFooter && (_jsxs(Stack, { gap: "xs", className: "mt-3 border-t border-neutral-100", padding: "t-sm", children: [showStoreLink && (_jsxs(Link, { href: String(ROUTES.PUBLIC.STORE_DETAIL(review.storeSlug)), className: "flex items-center gap-1.5 text-xs font-medium text-primary hover:underline", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83C\uDFEA" }), _jsx(Span, { truncate: true, children: review.storeName })] })), showProductLink && (_jsxs(Link, { href: productHref, className: "flex items-center gap-1.5 text-xs font-medium text-neutral-500 dark:text-zinc-400 hover:text-neutral-700 dark:hover:text-zinc-200", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDCE6" }), _jsx(Span, { truncate: true, children: review.productTitle ?? "View Product" }), _jsx(Span, { "aria-hidden": "true", className: "ml-auto text-primary group-hover:translate-x-0.5 transition-transform", children: "\u2192" })] })), showProfileLink && (_jsxs(Link, { href: profileHref, className: "flex items-center gap-1.5 text-xs font-medium text-neutral-500 dark:text-zinc-400 hover:text-neutral-700 dark:hover:text-zinc-200", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDC64" }), _jsx(Span, { truncate: true, children: displayName })] }))] }))] }));
37
31
  }
38
32
  export function ReviewsList({ reviews, context = "general", isLoading, totalPages = 1, currentPage = 1, onPageChange, emptyLabel = "No reviews yet", }) {
39
33
  if (isLoading) {
@@ -18,13 +18,11 @@ class ReviewRepository extends BaseRepository {
18
18
  ...result,
19
19
  items: result.items.map((item) => decryptPiiFields(item, [
20
20
  ...REVIEW_PII_FIELDS,
21
- // audit-unknown-ok: TS structural escape — domain document type lacks index signature
22
21
  ])),
23
22
  };
24
23
  }
25
24
  encryptReviewData(data) {
26
25
  let encrypted = encryptPiiFields(data, [...REVIEW_PII_FIELDS]);
27
- // audit-unknown-ok: TS structural escape — generic param
28
26
  encrypted = addPiiIndices(data, REVIEW_PII_INDEX_MAP);
29
27
  encrypted = {
30
28
  ...encryptPiiFields(data, [...REVIEW_PII_FIELDS]),
@@ -36,7 +34,6 @@ class ReviewRepository extends BaseRepository {
36
34
  const raw = super.mapDoc(snap);
37
35
  return decryptPiiFields(raw, [
38
36
  ...REVIEW_PII_FIELDS,
39
- // audit-unknown-ok: TS structural escape — generic param
40
37
  ]);
41
38
  }
42
39
  async create(input) {
@@ -43,7 +43,7 @@ export async function getPublicScammerById(id) {
43
43
  if (!doc || doc.status !== "verified")
44
44
  return null;
45
45
  // Increment views — non-blocking.
46
- scammerRepository.incrementViews(doc.id).catch(() => { }); // audit-silent-catch-ok: view-count is best-effort analytics
46
+ scammerRepository.incrementViews(doc.id).catch(() => { });
47
47
  return doc;
48
48
  }
49
49
  /**
@@ -57,7 +57,5 @@ export function ScamProfileView({ scammer, isAuthenticated, incidents = [], comm
57
57
  { label: "Home", href: "/" },
58
58
  { label: "Scam Registry", href: registryHref },
59
59
  { label: scammer.displayNames[0] ?? "Profile" },
60
- ] }) }) }), _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Grid, { cols: "twoThird", gap: "lg", children: [_jsxs(Stack, { gap: "lg", children: [_jsx(ScammerHeaderCard, { scammer: scammer }), (scammer.phones.length > 0 || scammer.upiIds.length > 0 || scammer.emails.length > 0) && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Contact Identifiers" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [scammer.phones.map((p) => (_jsx(IdentityChip, { label: "Phone", value: p, icon: _jsx(Phone, { className: "h-4 w-4" }) }, p))), scammer.upiIds.map((u) => (_jsx(IdentityChip, { label: "UPI ID", value: u, icon: _jsx(Wallet, { className: "h-4 w-4" }) }, u))), scammer.emails.map((e) => (_jsx(IdentityChip, { label: "Email", value: e, icon: _jsx(Mail, { className: "h-4 w-4" }) }, e)))] })] })), scammer.socialMedia.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Social Media Profiles" }), _jsx(Stack, { gap: "xs", children: scammer.socialMedia.map((sm, i) => (_jsxs(Row, { gap: "sm", align: "center", children: [_jsx(ExternalLink, { className: "h-4 w-4 shrink-0 text-[color:var(--appkit-color-text-muted,theme(colors.zinc.400))]" }), _jsxs(Text, { size: "sm", weight: "medium", children: [SOCIAL_PLATFORM_LABELS[sm.platform] ?? sm.platform, ":"] }), sm.url ? (_jsx(Anchor, { href: sm.url, size: "sm", children: sm.handle })) : (_jsx(Text, { variant: "secondary", size: "sm", children: sm.handle }))] }, i))) })] })), scammer.itemInvolved && (_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Item Involved" }), _jsx(Text, { variant: "secondary", size: "sm", children: scammer.itemInvolved })] })), _jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "What Happened" }), _jsx(Card, { variant: "flat", padding: "md", children: _jsx(Text, { className: "leading-relaxed", size: "sm", children: scammer.description }) })] }), scamTypeDef && scamTypeDef.howToAvoid.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "How to Avoid This Scam" }), _jsx(Card, { variant: "flat", padding: "md", children: _jsx(Stack, { gap: "xs", as: "ol", children: scamTypeDef.howToAvoid.map((tip, i) => (_jsxs(Row, { gap: "sm", align: "start", as: "li", children: [_jsx(Span, { layout: "flex-center", size: "xs", weight: "bold", className: "h-5 w-5 shrink-0 bg-[color:var(--appkit-color-success,theme(colors.green.600))]/10 text-[color:var(--appkit-color-success,theme(colors.green.700))]", rounded: "full", children: i + 1 }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", size: "sm", children: tip })] }, i))) }) })] })), scammer.evidence.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Evidence" }), _jsx(Row, { gap: "sm", wrap: true, children: scammer.evidence.map((url, i) => (
61
- // audit-variant-ok: evidence thumbnail Anchor — h-32/w-32 fixed size + border + shadow-sm card composition
62
- _jsx(Anchor, { href: url, underline: "none", className: "block h-32 w-32 rounded-lg overflow-hidden border shadow-sm hover:opacity-90", children: _jsx(MediaImage, { src: url, alt: `Evidence ${i + 1}`, size: "thumbnail" }) }, i))) })] })), _jsx(ScammerIncidentsSection, { incidents: incidents }), _jsx(ScammerCommentsSection, { comments: comments, isAuthenticated: isAuthenticated, scammerId: scammer.id }), relatedScammers.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Related Profiles" }), _jsx(Stack, { gap: "sm", children: relatedScammers.map((rel) => (_jsx(Link, { href: String(ROUTES.PUBLIC.SCAM_DETAIL(rel.id)), className: "block", children: _jsx(Card, { variant: "outlined", padding: "sm", className: "hover:opacity-80 transition-opacity", children: _jsxs(Row, { gap: "sm", align: "center", justify: "between", children: [_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", children: rel.displayNames[0] }), _jsx(Text, { variant: "secondary", size: "xs", children: SCAM_TYPE_LABELS[rel.scamType] ?? rel.scamType })] }), _jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Badge, { variant: statusVariant(rel.status), children: SCAMMER_STATUS_LABELS[rel.status] ?? rel.status }), _jsx(Link2, { className: "h-4 w-4 text-[color:var(--appkit-color-text-muted,theme(colors.zinc.400))]" })] })] }) }) }, rel.id))) })] }))] }), _jsx(ScammerActionsColumn, { scammer: scammer, isAuthenticated: isAuthenticated, reportHref: reportHref, contestLoginHref: contestLoginHref })] }) }) })] }));
60
+ ] }) }) }), _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Grid, { cols: "twoThird", gap: "lg", children: [_jsxs(Stack, { gap: "lg", children: [_jsx(ScammerHeaderCard, { scammer: scammer }), (scammer.phones.length > 0 || scammer.upiIds.length > 0 || scammer.emails.length > 0) && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Contact Identifiers" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [scammer.phones.map((p) => (_jsx(IdentityChip, { label: "Phone", value: p, icon: _jsx(Phone, { className: "h-4 w-4" }) }, p))), scammer.upiIds.map((u) => (_jsx(IdentityChip, { label: "UPI ID", value: u, icon: _jsx(Wallet, { className: "h-4 w-4" }) }, u))), scammer.emails.map((e) => (_jsx(IdentityChip, { label: "Email", value: e, icon: _jsx(Mail, { className: "h-4 w-4" }) }, e)))] })] })), scammer.socialMedia.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Social Media Profiles" }), _jsx(Stack, { gap: "xs", children: scammer.socialMedia.map((sm, i) => (_jsxs(Row, { gap: "sm", align: "center", children: [_jsx(ExternalLink, { className: "h-4 w-4 shrink-0 text-[color:var(--appkit-color-text-muted,theme(colors.zinc.400))]" }), _jsxs(Text, { size: "sm", weight: "medium", children: [SOCIAL_PLATFORM_LABELS[sm.platform] ?? sm.platform, ":"] }), sm.url ? (_jsx(Anchor, { href: sm.url, size: "sm", children: sm.handle })) : (_jsx(Text, { variant: "secondary", size: "sm", children: sm.handle }))] }, i))) })] })), scammer.itemInvolved && (_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Item Involved" }), _jsx(Text, { variant: "secondary", size: "sm", children: scammer.itemInvolved })] })), _jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "What Happened" }), _jsx(Card, { variant: "flat", padding: "md", children: _jsx(Text, { className: "leading-relaxed", size: "sm", children: scammer.description }) })] }), scamTypeDef && scamTypeDef.howToAvoid.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "How to Avoid This Scam" }), _jsx(Card, { variant: "flat", padding: "md", children: _jsx(Stack, { gap: "xs", as: "ol", children: scamTypeDef.howToAvoid.map((tip, i) => (_jsxs(Row, { gap: "sm", align: "start", as: "li", children: [_jsx(Span, { layout: "flex-center", size: "xs", weight: "bold", className: "h-5 w-5 shrink-0 bg-[color:var(--appkit-color-success,theme(colors.green.600))]/10 text-[color:var(--appkit-color-success,theme(colors.green.700))]", rounded: "full", children: i + 1 }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", size: "sm", children: tip })] }, i))) }) })] })), scammer.evidence.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Evidence" }), _jsx(Row, { gap: "sm", wrap: true, children: scammer.evidence.map((url, i) => (_jsx(Anchor, { href: url, underline: "none", className: "block h-32 w-32 rounded-lg overflow-hidden border shadow-sm hover:opacity-90", children: _jsx(MediaImage, { src: url, alt: `Evidence ${i + 1}`, size: "thumbnail" }) }, i))) })] })), _jsx(ScammerIncidentsSection, { incidents: incidents }), _jsx(ScammerCommentsSection, { comments: comments, isAuthenticated: isAuthenticated, scammerId: scammer.id }), relatedScammers.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "base", weight: "semibold", children: "Related Profiles" }), _jsx(Stack, { gap: "sm", children: relatedScammers.map((rel) => (_jsx(Link, { href: String(ROUTES.PUBLIC.SCAM_DETAIL(rel.id)), className: "block", children: _jsx(Card, { variant: "outlined", padding: "sm", className: "hover:opacity-80 transition-opacity", children: _jsxs(Row, { gap: "sm", align: "center", justify: "between", children: [_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", children: rel.displayNames[0] }), _jsx(Text, { variant: "secondary", size: "xs", children: SCAM_TYPE_LABELS[rel.scamType] ?? rel.scamType })] }), _jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Badge, { variant: statusVariant(rel.status), children: SCAMMER_STATUS_LABELS[rel.status] ?? rel.status }), _jsx(Link2, { className: "h-4 w-4 text-[color:var(--appkit-color-text-muted,theme(colors.zinc.400))]" })] })] }) }) }, rel.id))) })] }))] }), _jsx(ScammerActionsColumn, { scammer: scammer, isAuthenticated: isAuthenticated, reportHref: reportHref, contestLoginHref: contestLoginHref })] }) }) })] }));
63
61
  }