@mohasinac/appkit 4.10.0 → 4.11.1

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 (324) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +4 -1
  3. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +1 -1
  4. package/dist/_internal/client/features/lottery/LotteryPullForm.js +2 -2
  5. package/dist/_internal/server/features/admin/daily-digest-actions.d.ts +18 -0
  6. package/dist/_internal/server/features/admin/daily-digest-actions.js +37 -0
  7. package/dist/_internal/server/features/audit-log/actions.d.ts +25 -0
  8. package/dist/_internal/server/features/audit-log/actions.js +38 -0
  9. package/dist/_internal/server/features/brands/actions.js +0 -2
  10. package/dist/_internal/server/features/brands/og.d.ts +4 -1
  11. package/dist/_internal/server/features/brands/og.js +1 -1
  12. package/dist/_internal/server/features/grouped/data.d.ts +4 -0
  13. package/dist/_internal/server/features/grouped/data.js +24 -0
  14. package/dist/_internal/server/features/grouped/index.d.ts +1 -1
  15. package/dist/_internal/server/features/grouped/index.js +1 -1
  16. package/dist/_internal/server/features/orders/actions.js +9 -0
  17. package/dist/_internal/server/features/orders/adapters.js +25 -0
  18. package/dist/_internal/server/features/products/data.d.ts +2 -2
  19. package/dist/_internal/server/features/products/data.js +5 -23
  20. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  21. package/dist/_internal/server/functions/scheduled.js +17 -1
  22. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +40 -0
  23. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +164 -0
  24. package/dist/_internal/server/jobs/core/hardBanCascade.js +11 -0
  25. package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +1 -0
  26. package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +4 -1
  27. package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +12 -0
  28. package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +85 -0
  29. package/dist/_internal/server/jobs/core/whatsappNotify.js +16 -0
  30. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.d.ts +2 -0
  31. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.js +4 -0
  32. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  33. package/dist/_internal/server/jobs/handlers/index.js +3 -0
  34. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +2 -0
  35. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +2 -0
  36. package/dist/_internal/server/notifications/channel-health.d.ts +27 -0
  37. package/dist/_internal/server/notifications/channel-health.js +101 -0
  38. package/dist/_internal/shared/features/brands/schema.d.ts +0 -6
  39. package/dist/_internal/shared/features/brands/schema.js +0 -1
  40. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +7 -0
  41. package/dist/_internal/shared/features/categories/bundle-schemas.js +3 -0
  42. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  43. package/dist/_internal/shared/features/products/to-product-item.d.ts +25 -0
  44. package/dist/_internal/shared/features/products/to-product-item.js +45 -0
  45. package/dist/client.d.ts +21 -6
  46. package/dist/client.js +13 -3
  47. package/dist/constants/api-endpoints.d.ts +6 -9
  48. package/dist/constants/api-endpoints.js +2 -3
  49. package/dist/contracts/client-auth.d.ts +3 -7
  50. package/dist/contracts/email.d.ts +1 -0
  51. package/dist/features/account/components/AddressForm.js +24 -2
  52. package/dist/features/account/components/BecomeSellerView.d.ts +1 -2
  53. package/dist/features/account/components/BecomeSellerView.js +1 -1
  54. package/dist/features/account/components/NotificationBell.js +1 -1
  55. package/dist/features/account/components/UserBidsView.d.ts +1 -0
  56. package/dist/features/account/components/UserBidsView.js +47 -0
  57. package/dist/features/account/components/UserOrdersView.d.ts +4 -11
  58. package/dist/features/account/components/UserOrdersView.js +54 -4
  59. package/dist/features/account/components/UserReturnsView.d.ts +4 -9
  60. package/dist/features/account/components/UserReturnsView.js +37 -3
  61. package/dist/features/account/components/index.d.ts +3 -2
  62. package/dist/features/account/components/index.js +1 -0
  63. package/dist/features/admin/actions/admin-actions.js +22 -0
  64. package/dist/features/admin/actions/admin-coupon-actions.js +10 -0
  65. package/dist/features/admin/actions/notification-actions.js +4 -3
  66. package/dist/features/admin/components/AdminAdsView.d.ts +2 -3
  67. package/dist/features/admin/components/AdminAdsView.js +86 -89
  68. package/dist/features/admin/components/AdminAllEventEntriesView.js +18 -3
  69. package/dist/features/admin/components/AdminAuditLogView.d.ts +11 -0
  70. package/dist/features/admin/components/AdminAuditLogView.js +95 -0
  71. package/dist/features/admin/components/AdminBlogEditorView.js +37 -3
  72. package/dist/features/admin/components/AdminBrandEditorView.js +10 -6
  73. package/dist/features/admin/components/AdminBundleEditorView.js +18 -2
  74. package/dist/features/admin/components/AdminCarouselEditorView.js +2 -2
  75. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +2 -2
  76. package/dist/features/admin/components/AdminCartsView.js +34 -4
  77. package/dist/features/admin/components/AdminCategoryEditorView.js +5 -4
  78. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  79. package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
  80. package/dist/features/admin/components/AdminHistoryView.js +11 -1
  81. package/dist/features/admin/components/AdminNotificationsView.js +27 -1
  82. package/dist/features/admin/components/AdminOrderEditorView.d.ts +10 -1
  83. package/dist/features/admin/components/AdminOrderEditorView.js +4 -3
  84. package/dist/features/admin/components/AdminOrdersView.js +92 -24
  85. package/dist/features/admin/components/AdminPayoutMarkPaidModal.d.ts +7 -0
  86. package/dist/features/admin/components/AdminPayoutMarkPaidModal.js +47 -0
  87. package/dist/features/admin/components/AdminPayoutsView.js +15 -31
  88. package/dist/features/admin/components/AdminProductEditorView.js +26 -3
  89. package/dist/features/admin/components/AdminSiteSettingsView.js +20 -1
  90. package/dist/features/admin/components/AdminStoreAddressesView.js +22 -2
  91. package/dist/features/admin/components/AdminStoresView.js +7 -0
  92. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +2 -2
  93. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +2 -2
  94. package/dist/features/admin/components/AdminUserEditorView.d.ts +2 -2
  95. package/dist/features/admin/components/AdminUserEditorView.js +4 -2
  96. package/dist/features/admin/components/AdminUsersView.js +1 -1
  97. package/dist/features/admin/components/AdminWishlistsView.js +14 -1
  98. package/dist/features/admin/components/DataListingView.d.ts +2 -2
  99. package/dist/features/admin/components/ViewAuditLogEntryModal.d.ts +19 -0
  100. package/dist/features/admin/components/ViewAuditLogEntryModal.js +22 -0
  101. package/dist/features/admin/components/ViewNotificationModal.d.ts +21 -0
  102. package/dist/features/admin/components/ViewNotificationModal.js +15 -0
  103. package/dist/features/admin/components/analytics/AdminPageViewsReportView.d.ts +4 -7
  104. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +56 -36
  105. package/dist/features/admin/components/index.d.ts +8 -1
  106. package/dist/features/admin/components/index.js +4 -0
  107. package/dist/features/admin/constants/filter-tabs.d.ts +49 -0
  108. package/dist/features/admin/constants/filter-tabs.js +27 -0
  109. package/dist/features/admin/hooks/useAdminListing.d.ts +6 -0
  110. package/dist/features/admin/hooks/useAdminListing.js +3 -1
  111. package/dist/features/admin/hooks/useAdminListingData.d.ts +9 -1
  112. package/dist/features/admin/hooks/useAdminListingData.js +9 -2
  113. package/dist/features/admin/repository/site-settings.repository.d.ts +5 -0
  114. package/dist/features/admin/schemas/firestore.d.ts +12 -0
  115. package/dist/features/analytics/types.d.ts +1 -1
  116. package/dist/features/analytics/types.js +8 -0
  117. package/dist/features/auctions/schemas/index.d.ts +5 -0
  118. package/dist/features/audit-log/repository/audit-log.repository.d.ts +45 -0
  119. package/dist/features/audit-log/repository/audit-log.repository.js +30 -0
  120. package/dist/features/audit-log/schemas/firestore.d.ts +59 -0
  121. package/dist/features/audit-log/schemas/firestore.js +35 -0
  122. package/dist/features/auth/actions/index.d.ts +0 -1
  123. package/dist/features/auth/actions/index.js +0 -1
  124. package/dist/features/auth/hooks/useAuth.d.ts +8 -35
  125. package/dist/features/auth/hooks/useAuth.js +21 -37
  126. package/dist/features/auth/permissions/constants.d.ts +1 -1
  127. package/dist/features/auth/permissions/constants.js +2 -0
  128. package/dist/features/blog/schemas/index.d.ts +32 -0
  129. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +31 -3
  130. package/dist/features/catalogue/components/CatalogueItemEditorView.js +2 -1
  131. package/dist/features/categories/components/BrandDetailPageView.js +14 -12
  132. package/dist/features/categories/components/CategoryDetailPageView.js +7 -3
  133. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.d.ts +14 -0
  134. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.js +22 -0
  135. package/dist/features/categories/components/CategoryProductsView.d.ts +1 -5
  136. package/dist/features/categories/components/CategoryProductsView.js +1 -1
  137. package/dist/features/categories/components/CategorySelectorCreate.js +16 -2
  138. package/dist/features/categories/schemas/firestore.d.ts +19 -2
  139. package/dist/features/categories/schemas/index.d.ts +24 -3
  140. package/dist/features/categories/schemas/index.js +3 -1
  141. package/dist/features/categories/types/index.d.ts +7 -0
  142. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +17 -3
  143. package/dist/features/checkout/actions/checkout-value-otp-actions.js +101 -22
  144. package/dist/features/contact/components/ContactForm.js +17 -4
  145. package/dist/features/contact/email.d.ts +1 -0
  146. package/dist/features/contact/email.js +3 -0
  147. package/dist/features/events/components/AdminEventEditorView.js +54 -2
  148. package/dist/features/events/components/AdminEventEntriesView.d.ts +2 -16
  149. package/dist/features/events/components/AdminEventEntriesView.js +56 -89
  150. package/dist/features/events/components/EventFormDrawer.js +5 -1
  151. package/dist/features/events/components/EventRaffleEntryForm.d.ts +1 -3
  152. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  153. package/dist/features/events/schemas/index.d.ts +22 -0
  154. package/dist/features/grouped/components/GroupedListingsCarousel.js +4 -1
  155. package/dist/features/grouped/repository/grouped-listings.repository.d.ts +4 -0
  156. package/dist/features/grouped/repository/grouped-listings.repository.js +18 -0
  157. package/dist/features/homepage/components/CharacterHotspotForm.js +202 -187
  158. package/dist/features/homepage/components/SectionCarousel.d.ts +1 -7
  159. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  160. package/dist/features/layout/TitleBarLayout.d.ts +1 -1
  161. package/dist/features/layout/TitleBarLayout.js +3 -3
  162. package/dist/features/media/MediaImage.js +39 -3
  163. package/dist/features/media/types/index.d.ts +10 -0
  164. package/dist/features/media/types/index.js +1 -0
  165. package/dist/features/media/upload/MediaUploadField.d.ts +7 -1
  166. package/dist/features/media/upload/MediaUploadField.js +11 -7
  167. package/dist/features/media/upload/video-poster.d.ts +2 -0
  168. package/dist/features/media/upload/video-poster.js +16 -1
  169. package/dist/features/media/upload/video-poster.test.js +1 -1
  170. package/dist/features/orders/components/OrderStatusTimeline.d.ts +12 -0
  171. package/dist/features/orders/components/OrderStatusTimeline.js +55 -0
  172. package/dist/features/orders/components/index.d.ts +2 -0
  173. package/dist/features/orders/components/index.js +1 -0
  174. package/dist/features/orders/constants/payment-window.d.ts +25 -0
  175. package/dist/features/orders/constants/payment-window.js +25 -0
  176. package/dist/features/orders/repository/orders.repository.d.ts +32 -0
  177. package/dist/features/orders/repository/orders.repository.js +56 -0
  178. package/dist/features/orders/schemas/index.d.ts +24 -24
  179. package/dist/features/orders/types/index.d.ts +33 -0
  180. package/dist/features/pre-orders/schemas/index.d.ts +5 -0
  181. package/dist/features/products/components/BidHistory.js +9 -1
  182. package/dist/features/products/components/GroupSettingsPanel.js +25 -3
  183. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  184. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +1 -4
  185. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  186. package/dist/features/products/components/ProductDetailActions.d.ts +1 -2
  187. package/dist/features/products/components/ProductDetailActions.js +1 -1
  188. package/dist/features/products/components/ProductGrid.js +15 -1
  189. package/dist/features/products/constants/action-defs.d.ts +1 -0
  190. package/dist/features/products/constants/action-defs.js +1 -0
  191. package/dist/features/products/schemas/index.d.ts +5 -0
  192. package/dist/features/promotions/components/CouponsIndexListing.d.ts +1 -3
  193. package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
  194. package/dist/features/search/components/SearchView.d.ts +1 -3
  195. package/dist/features/search/components/SearchView.js +1 -1
  196. package/dist/features/seller/components/QuickProductForm.js +2 -1
  197. package/dist/features/seller/components/SellerBidsView.js +66 -107
  198. package/dist/features/seller/components/SellerGoogleReviewsView.js +17 -1
  199. package/dist/features/seller/components/SellerOrdersView.d.ts +15 -3
  200. package/dist/features/seller/components/SellerOrdersView.js +134 -163
  201. package/dist/features/seller/components/SellerPayoutMethodsView.js +60 -48
  202. package/dist/features/seller/components/SellerPayoutSettingsView.js +69 -4
  203. package/dist/features/seller/components/SellerPayoutsView.d.ts +12 -0
  204. package/dist/features/seller/components/SellerPayoutsView.js +25 -5
  205. package/dist/features/seller/components/SellerProductShell.d.ts +10 -3
  206. package/dist/features/seller/components/SellerProductShell.js +89 -36
  207. package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +2 -7
  208. package/dist/features/seller/components/SellerProductsFilterDrawer.js +4 -4
  209. package/dist/features/seller/components/SellerProductsView.d.ts +2 -4
  210. package/dist/features/seller/components/SellerProductsView.js +131 -189
  211. package/dist/features/seller/components/SellerReviewsView.js +95 -133
  212. package/dist/features/seller/components/SellerShippingConfigsView.js +47 -67
  213. package/dist/features/seller/components/SellerShippingView.js +41 -4
  214. package/dist/features/seller/components/SellerStoreCategoriesView.js +51 -59
  215. package/dist/features/seller/components/SellerStorefrontView.d.ts +6 -1
  216. package/dist/features/seller/components/SellerStorefrontView.js +42 -5
  217. package/dist/features/seller/components/index.d.ts +2 -2
  218. package/dist/features/seller/components/index.js +2 -2
  219. package/dist/features/shell/FormShell.d.ts +24 -4
  220. package/dist/features/shell/FormShell.js +12 -6
  221. package/dist/features/shell/QuickFormDrawer.js +67 -12
  222. package/dist/features/shell/StepForm.d.ts +30 -1
  223. package/dist/features/shell/StepForm.js +47 -4
  224. package/dist/features/shell/index.d.ts +1 -1
  225. package/dist/features/shell/index.js +1 -1
  226. package/dist/features/shipments/components/AdminShipmentEditorView.js +2 -2
  227. package/dist/features/shipments/schemas/validation.d.ts +14 -4
  228. package/dist/features/tester/components/AdminTesterFeedbackListView.js +23 -2
  229. package/dist/features/tester/components/TesterChecklistStepRow.js +1 -1
  230. package/dist/features/tester/components/TesterHubView.js +3 -2
  231. package/dist/features/tester/seed-data/orders-tester-seed-data.js +9 -1
  232. package/dist/features/tester/seed-data/products-tester-seed-data.js +43 -32
  233. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +404 -15
  234. package/dist/index.d.ts +15 -3
  235. package/dist/index.js +22 -5
  236. package/dist/next/routing/route-map.d.ts +11 -0
  237. package/dist/next/routing/route-map.js +5 -0
  238. package/dist/providers/email-resend/provider.js +1 -0
  239. package/dist/providers/firebase-client/auth.d.ts +1 -0
  240. package/dist/providers/firebase-client/auth.js +7 -1
  241. package/dist/repositories/index.d.ts +1 -0
  242. package/dist/repositories/index.js +1 -0
  243. package/dist/schemas/registry.d.ts +61 -25
  244. package/dist/security/pii-mask.js +1 -1
  245. package/dist/seed/categories-seed-data.js +69 -0
  246. package/dist/seed/products-auctions-seed-data.js +11 -0
  247. package/dist/seed/products-standard-seed-data.js +93 -4
  248. package/dist/seed/site-settings-seed-data.js +13 -1
  249. package/dist/seed/store-extensions-seed-data.js +1 -1
  250. package/dist/server-entry.d.ts +2 -1
  251. package/dist/server-entry.js +20 -2
  252. package/dist/server.d.ts +7 -2
  253. package/dist/server.js +8 -3
  254. package/dist/styles.css +1 -1
  255. package/dist/tailwind-utilities.css +1 -1
  256. package/dist/ui/components/Form.d.ts +11 -2
  257. package/dist/ui/components/Form.js +4 -3
  258. package/dist/ui/components/FormField.d.ts +3 -1
  259. package/dist/ui/components/FormField.js +22 -4
  260. package/dist/ui/components/ListingLayout.d.ts +1 -2
  261. package/dist/ui/components/ListingLayout.js +1 -1
  262. package/dist/ui/components/RecordDetailModal.d.ts +68 -0
  263. package/dist/ui/components/RecordDetailModal.js +8 -0
  264. package/dist/ui/components/SlottedListingView.js +9 -1
  265. package/dist/ui/forms/FormErrorSummary.d.ts +25 -0
  266. package/dist/ui/forms/FormErrorSummary.js +37 -0
  267. package/dist/ui/forms/FormShell.d.ts +37 -2
  268. package/dist/ui/forms/FormShell.js +37 -7
  269. package/dist/ui/forms/FormShell.style.css +17 -0
  270. package/dist/ui/forms/index.d.ts +2 -0
  271. package/dist/ui/forms/index.js +1 -0
  272. package/dist/ui/index.d.ts +4 -0
  273. package/dist/ui/index.js +5 -0
  274. package/dist/utils/media-url.d.ts +3 -1
  275. package/dist/utils/media-url.js +20 -1
  276. package/dist/validation/schemas.d.ts +4 -4
  277. package/package.json +1 -1
  278. package/dist/_internal/client/features/classified/ClassifiedDetailView.d.ts +0 -9
  279. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +0 -55
  280. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.d.ts +0 -18
  281. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +0 -21
  282. package/dist/_internal/client/features/live/LiveItemDetailView.d.ts +0 -9
  283. package/dist/_internal/client/features/live/LiveItemDetailView.js +0 -25
  284. package/dist/_internal/server/jobs/core/prizeRevealClose.d.ts +0 -2
  285. package/dist/_internal/server/jobs/core/prizeRevealClose.js +0 -28
  286. package/dist/_internal/server/jobs/core/prizeRevealExpiry.d.ts +0 -2
  287. package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +0 -61
  288. package/dist/_internal/server/jobs/core/prizeRevealOpen.d.ts +0 -2
  289. package/dist/_internal/server/jobs/core/prizeRevealOpen.js +0 -68
  290. package/dist/_internal/server/jobs/core/prizeRevealReminder.d.ts +0 -2
  291. package/dist/_internal/server/jobs/core/prizeRevealReminder.js +0 -49
  292. package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +0 -2
  293. package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +0 -2
  294. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +0 -2
  295. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +0 -2
  296. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +0 -2
  297. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +0 -2
  298. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +0 -2
  299. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +0 -2
  300. package/dist/features/auth/consent-otp.d.ts +0 -57
  301. package/dist/features/auth/consent-otp.js +0 -127
  302. package/dist/features/cart/components/CheckoutOtpModal.d.ts +0 -15
  303. package/dist/features/cart/components/CheckoutOtpModal.js +0 -12
  304. package/dist/features/checkout/actions/checkout-actions.d.ts +0 -31
  305. package/dist/features/checkout/actions/checkout-actions.js +0 -124
  306. package/dist/features/classified/components/ClassifiedIndexListing.d.ts +0 -5
  307. package/dist/features/classified/components/ClassifiedIndexListing.js +0 -123
  308. package/dist/features/classified/components/ClassifiedListView.d.ts +0 -6
  309. package/dist/features/classified/components/ClassifiedListView.js +0 -44
  310. package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +0 -5
  311. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +0 -114
  312. package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +0 -6
  313. package/dist/features/digital-codes/components/DigitalCodesListView.js +0 -38
  314. package/dist/features/live/components/LiveItemsIndexListing.d.ts +0 -5
  315. package/dist/features/live/components/LiveItemsIndexListing.js +0 -115
  316. package/dist/features/live/components/LiveItemsListView.d.ts +0 -6
  317. package/dist/features/live/components/LiveItemsListView.js +0 -44
  318. package/dist/features/seller/components/SellerTemplatesView.d.ts +0 -12
  319. package/dist/features/seller/components/SellerTemplatesView.js +0 -276
  320. package/dist/react/hooks/useVisibleItems.d.ts +0 -37
  321. package/dist/react/hooks/useVisibleItems.js +0 -59
  322. package/dist/ui/components/TabStrip.d.ts +0 -34
  323. package/dist/ui/components/TabStrip.js +0 -56
  324. package/dist/ui/components/TabStrip.style.css +0 -97
@@ -570,15 +570,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
570
570
  bin: string;
571
571
  } | undefined;
572
572
  payoutStatus?: "paid" | "eligible" | "requested" | undefined;
573
- items?: {
574
- productId: string;
575
- productTitle: string;
576
- quantity: number;
577
- unitPrice: number;
578
- totalPrice: number;
579
- listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
580
- prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
581
- }[] | undefined;
582
573
  paymentId?: string | undefined;
583
574
  shippingAddress?: string | undefined;
584
575
  trackingNumber?: string | undefined;
@@ -601,6 +592,15 @@ export declare const orderFirestoreSchema: z.ZodObject<{
601
592
  shippingMethod?: "custom" | undefined;
602
593
  shippingCarrier?: string | undefined;
603
594
  trackingUrl?: string | undefined;
595
+ items?: {
596
+ productId: string;
597
+ productTitle: string;
598
+ quantity: number;
599
+ unitPrice: number;
600
+ totalPrice: number;
601
+ listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
602
+ prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
603
+ }[] | undefined;
604
604
  bundleId?: string | undefined;
605
605
  prizeWon?: {
606
606
  title: string;
@@ -612,6 +612,8 @@ export declare const orderFirestoreSchema: z.ZodObject<{
612
612
  } | undefined;
613
613
  prizeDrawProductId?: string | undefined;
614
614
  couponCode?: string | undefined;
615
+ emiEnabled?: boolean | undefined;
616
+ emiTenureMonths?: number | undefined;
615
617
  orderType?: string | undefined;
616
618
  imageUrls?: string[] | undefined;
617
619
  refundFeeDeducted?: number | undefined;
@@ -627,8 +629,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
627
629
  couponId?: string | undefined;
628
630
  }[] | undefined;
629
631
  codHandlingFee?: number | undefined;
630
- emiEnabled?: boolean | undefined;
631
- emiTenureMonths?: number | undefined;
632
632
  emiTokenAmount?: number | undefined;
633
633
  emiSurchargeAmount?: number | undefined;
634
634
  emiInstallments?: {
@@ -718,15 +718,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
718
718
  bin: string;
719
719
  } | undefined;
720
720
  payoutStatus?: "paid" | "eligible" | "requested" | undefined;
721
- items?: {
722
- productId: string;
723
- productTitle: string;
724
- quantity: number;
725
- unitPrice: number;
726
- totalPrice: number;
727
- listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
728
- prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
729
- }[] | undefined;
730
721
  paymentId?: string | undefined;
731
722
  shippingAddress?: string | undefined;
732
723
  trackingNumber?: string | undefined;
@@ -749,6 +740,15 @@ export declare const orderFirestoreSchema: z.ZodObject<{
749
740
  shippingMethod?: "custom" | undefined;
750
741
  shippingCarrier?: string | undefined;
751
742
  trackingUrl?: string | undefined;
743
+ items?: {
744
+ productId: string;
745
+ productTitle: string;
746
+ quantity: number;
747
+ unitPrice: number;
748
+ totalPrice: number;
749
+ listingType?: "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | undefined;
750
+ prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
751
+ }[] | undefined;
752
752
  bundleId?: string | undefined;
753
753
  prizeWon?: {
754
754
  title: string;
@@ -760,6 +760,8 @@ export declare const orderFirestoreSchema: z.ZodObject<{
760
760
  } | undefined;
761
761
  prizeDrawProductId?: string | undefined;
762
762
  couponCode?: string | undefined;
763
+ emiEnabled?: boolean | undefined;
764
+ emiTenureMonths?: number | undefined;
763
765
  orderType?: string | undefined;
764
766
  imageUrls?: string[] | undefined;
765
767
  refundFeeDeducted?: number | undefined;
@@ -775,8 +777,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
775
777
  couponId?: string | undefined;
776
778
  }[] | undefined;
777
779
  codHandlingFee?: number | undefined;
778
- emiEnabled?: boolean | undefined;
779
- emiTenureMonths?: number | undefined;
780
780
  emiTokenAmount?: number | undefined;
781
781
  emiSurchargeAmount?: number | undefined;
782
782
  emiInstallments?: {
@@ -962,6 +962,7 @@ export declare const orderSchema: z.ZodObject<{
962
962
  [k: string]: unknown;
963
963
  };
964
964
  userId: string;
965
+ paymentStatus: string;
965
966
  items: {
966
967
  title: string;
967
968
  price: number;
@@ -972,7 +973,6 @@ export declare const orderSchema: z.ZodObject<{
972
973
  storeId?: string | undefined;
973
974
  attributes?: Record<string, string> | undefined;
974
975
  }[];
975
- paymentStatus: string;
976
976
  total: number;
977
977
  subtotal: number;
978
978
  orderStatus: "pending" | "cancelled" | "processing" | "refunded" | "delivered" | "confirmed" | "shipped" | "return_requested" | "returned";
@@ -999,6 +999,7 @@ export declare const orderSchema: z.ZodObject<{
999
999
  [k: string]: unknown;
1000
1000
  };
1001
1001
  userId: string;
1002
+ paymentStatus: string;
1002
1003
  items: {
1003
1004
  title: string;
1004
1005
  price: number;
@@ -1009,7 +1010,6 @@ export declare const orderSchema: z.ZodObject<{
1009
1010
  storeId?: string | undefined;
1010
1011
  attributes?: Record<string, string> | undefined;
1011
1012
  }[];
1012
- paymentStatus: string;
1013
1013
  total: number;
1014
1014
  subtotal: number;
1015
1015
  orderStatus: "pending" | "cancelled" | "processing" | "refunded" | "delivered" | "confirmed" | "shipped" | "return_requested" | "returned";
@@ -67,6 +67,8 @@ export interface Order {
67
67
  couponCode?: string;
68
68
  trackingNumber?: string;
69
69
  shippingCarrier?: string;
70
+ /** Carrier tracking page URL — rendered as an external link that opens in a new tab. No live-tracking API integration; this is just the passthrough URL a seller/admin entered. */
71
+ trackingUrl?: string;
70
72
  notes?: string;
71
73
  timeline?: OrderTimeline[];
72
74
  physicalLocation?: {
@@ -76,10 +78,41 @@ export interface Order {
76
78
  };
77
79
  createdAt?: string;
78
80
  updatedAt?: string;
81
+ /** Real per-status timestamps written by the order-status-update path — used to render a genuine status timeline (not fabricated/estimated). */
82
+ orderDate?: string;
83
+ shippingDate?: string;
84
+ deliveryDate?: string;
85
+ cancellationDate?: string;
79
86
  /** Tier PP — true when the 2-hour auto-approve sweep confirmed this order's payment instead of a manual admin review. Drives the "Raise a dispute" CTA. */
80
87
  autoApproved?: boolean;
81
88
  disputeRaised?: boolean;
82
89
  disputeStatus?: "open" | "resolved";
90
+ /**
91
+ * Manual-payment (cash / UPI / EMI) fields. Every one of these already
92
+ * existed on `OrderDocument` but was dropped by `orderDocumentToOrder`,
93
+ * so the buyer-facing surfaces that need them read `undefined`:
94
+ * `/user/orders/[id]/payment` gated its whole render on `paymentMethod`
95
+ * and therefore told every buyer "this order does not require manual
96
+ * payment upload", and the 15-minute countdown + UPI ID never rendered.
97
+ * (CLAUDE.md Root Cause Pattern #38 — adapter/serializer field drift.)
98
+ */
99
+ paymentMethod?: string;
100
+ /** UPI ID the buyer was told to pay to — shown on the payment page and diffed against `buyerReportedUpiId` during admin review. */
101
+ displayedUpiId?: string;
102
+ /** ISO end of the 15-minute payment window; drives the buyer countdown. */
103
+ paymentDeadline?: string;
104
+ paymentProofUrl?: string;
105
+ paymentProofUploadedAt?: string;
106
+ paymentTransactionId?: string;
107
+ buyerReportedUpiId?: string;
108
+ buyerMarkedPaid?: boolean;
109
+ paymentUpiMismatch?: boolean;
110
+ /** Admin decision on the submitted proof; unset means "not reviewed yet". */
111
+ paymentReviewOutcome?: "approved" | "reupload_requested" | "rejected_fraud";
112
+ /** Admin's note — the reason shown to the buyer on a re-upload request or fraud rejection. */
113
+ paymentReviewNote?: string;
114
+ /** Why the order was cancelled — distinguishes a payment-window expiry / fraud rejection from an ordinary cancellation. */
115
+ cancellationReason?: string;
83
116
  /**
84
117
  * Reveal-mode prize-draw fields (SB4-H/SB8-C). Set once the winner has
85
118
  * been automatically assigned to this order (on payment confirmation,
@@ -21,6 +21,7 @@ export declare const preorderItemSchema: z.ZodObject<{
21
21
  thumbnailUrl: z.ZodOptional<z.ZodString>;
22
22
  source: z.ZodOptional<z.ZodEnum<["upload", "youtube", "external"]>>;
23
23
  youtubeId: z.ZodOptional<z.ZodString>;
24
+ duration: z.ZodOptional<z.ZodNumber>;
24
25
  }, "strip", z.ZodTypeAny, {
25
26
  type: "video" | "image" | "file";
26
27
  url: string;
@@ -28,6 +29,7 @@ export declare const preorderItemSchema: z.ZodObject<{
28
29
  alt?: string | undefined;
29
30
  thumbnailUrl?: string | undefined;
30
31
  youtubeId?: string | undefined;
32
+ duration?: number | undefined;
31
33
  }, {
32
34
  type: "video" | "image" | "file";
33
35
  url: string;
@@ -35,6 +37,7 @@ export declare const preorderItemSchema: z.ZodObject<{
35
37
  alt?: string | undefined;
36
38
  thumbnailUrl?: string | undefined;
37
39
  youtubeId?: string | undefined;
40
+ duration?: number | undefined;
38
41
  }>, "many">>;
39
42
  salePrice: z.ZodNumber;
40
43
  regularPrice: z.ZodNumber;
@@ -62,6 +65,7 @@ export declare const preorderItemSchema: z.ZodObject<{
62
65
  alt?: string | undefined;
63
66
  thumbnailUrl?: string | undefined;
64
67
  youtubeId?: string | undefined;
68
+ duration?: number | undefined;
65
69
  }[] | undefined;
66
70
  franchise?: string | undefined;
67
71
  preorderShipDate?: string | undefined;
@@ -82,6 +86,7 @@ export declare const preorderItemSchema: z.ZodObject<{
82
86
  alt?: string | undefined;
83
87
  thumbnailUrl?: string | undefined;
84
88
  youtubeId?: string | undefined;
89
+ duration?: number | undefined;
85
90
  }[] | undefined;
86
91
  isFeatured?: boolean | undefined;
87
92
  franchise?: string | undefined;
@@ -19,6 +19,14 @@ function formatBidDate(raw) {
19
19
  return raw;
20
20
  }
21
21
  }
22
+ /** Bidder identity is already masked server-side (`maskPublicBid`) when a
23
+ * display name is present; this is only a fallback for bare bidder ids. */
24
+ function maskBidderId(id) {
25
+ if (!id)
26
+ return "Anonymous";
27
+ const tail = id.slice(-4);
28
+ return `Bidder ***${tail}`;
29
+ }
22
30
  export function BidHistory({ isLoading = false, isEmpty = false, renderList, renderBid, bids = [], renderEmpty, renderSkeleton, currency, labels = {}, className = "", }) {
23
31
  if (isLoading) {
24
32
  if (renderSkeleton)
@@ -32,5 +40,5 @@ export function BidHistory({ isLoading = false, isEmpty = false, renderList, ren
32
40
  }
33
41
  if (renderList)
34
42
  return _jsx(Div, { className: className, children: renderList() });
35
- return (_jsxs(Div, { className: className, children: [labels.title && (_jsx(Heading, { level: 3, className: "mb-3 tracking-wide", color: "muted", size: "sm", weight: "semibold", transform: "uppercase", children: labels.title })), _jsx(Stack, { gap: "sm", children: bids.map((bid, i) => renderBid ? (_jsx(React.Fragment, { children: renderBid(bid, i) }, bid.id)) : (_jsxs(Div, { layout: "flex", align: "center", justify: "between", rounded: "lg", padding: "sm", textSize: "sm", className: "border border-[var(--appkit-color-border-subtle)] bg-[var(--appkit-color-surface)]", "data-section": "bidhistory-div-422", children: [_jsx(Span, { weight: "bold", className: "text-primary-600 dark:text-primary-400", children: currency ? formatCurrency(bid.amount, currency) : bid.amount.toLocaleString() }), _jsx(Span, { size: "xs", color: "muted", children: formatBidDate(bid.placedAt) })] }, bid.id))) })] }));
43
+ return (_jsxs(Div, { className: className, children: [labels.title && (_jsx(Heading, { level: 3, className: "mb-3 tracking-wide", color: "muted", size: "sm", weight: "semibold", transform: "uppercase", children: labels.title })), _jsx(Stack, { gap: "sm", children: bids.map((bid, i) => renderBid ? (_jsx(React.Fragment, { children: renderBid(bid, i) }, bid.id)) : (_jsxs(Div, { layout: "flex", align: "center", justify: "between", rounded: "lg", padding: "sm", textSize: "sm", className: "border border-[var(--appkit-color-border-subtle)] bg-[var(--appkit-color-surface)]", "data-section": "bidhistory-div-422", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Span, { weight: "bold", className: "text-primary-600 dark:text-primary-400", children: currency ? formatCurrency(bid.amount, currency) : bid.amount.toLocaleString() }), _jsx(Span, { size: "xs", color: "muted", children: bid.bidderName || maskBidderId(bid.bidderId) })] }), _jsx(Span, { size: "xs", color: "muted", children: formatBidDate(bid.placedAt) })] }, bid.id))) })] }));
36
44
  }
@@ -1,12 +1,22 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
- import { useState } from "react";
4
+ import { useEffect, useState } from "react";
5
+ import { z } from "zod";
5
6
  import { Button, Code, ConfirmDeleteModal, Div, FormField, Heading, Modal, Row, Select, SideDrawer, Span, Stack, Tabs, TabsContent, TabsList, TabsTrigger, Text, useToast } from "../../../ui";
7
+ import { FormShellContext, useFormShellState, FormErrorSummary } from "../../../ui/forms";
6
8
  import { MediaImage } from "../../media/MediaImage";
7
9
  import { apiClient } from "../../../http";
8
10
  import { PRODUCT_ENDPOINTS } from "../../../constants/api-endpoints";
9
11
  import { ProductInlineSelect } from "../../seller/components/ProductInlineSelect";
12
+ const groupTitleSchema = z.object({
13
+ groupTitle: z.string().min(1, "Group title is required"),
14
+ });
15
+ const createChildSchema = z.object({
16
+ title: z.string().min(1, "Title is required"),
17
+ price: z.string().refine((v) => v.trim() !== "" && !Number.isNaN(parseFloat(v)) && parseFloat(v) > 0, "Enter a valid price"),
18
+ condition: z.string(),
19
+ });
10
20
  const __P = {
11
21
  p4: "p-[var(--appkit-space-4)]",
12
22
  };
@@ -33,6 +43,11 @@ export function GroupSettingsPanel({ productId, productSlug, groupId, isGroupPar
33
43
  const [linkTargets, setLinkTargets] = useState([]);
34
44
  const [children, setChildren] = useState(null);
35
45
  const [confirmAction, setConfirmAction] = useState(null);
46
+ const { shellCtx: titleShellCtx, validate: validateTitle } = useFormShellState(groupTitleSchema);
47
+ useEffect(() => {
48
+ validateTitle({ groupTitle: editTitle });
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ }, [editTitle, validateTitle]);
36
51
  if (isAuction)
37
52
  return null;
38
53
  const groupEndpoint = `${storeProductsEndpoint}/${productId}/group`;
@@ -69,6 +84,8 @@ export function GroupSettingsPanel({ productId, productSlug, groupId, isGroupPar
69
84
  }
70
85
  }
71
86
  async function saveTitle() {
87
+ if (Object.keys(titleShellCtx.errors).length > 0)
88
+ return;
72
89
  setLoading(true);
73
90
  try {
74
91
  await apiClient.patch(groupEndpoint, { groupTitle: editTitle });
@@ -218,8 +235,13 @@ export function GroupSettingsPanel({ productId, productSlug, groupId, isGroupPar
218
235
  setOpen(next);
219
236
  if (next && isGroupParent && children === null)
220
237
  loadChildren();
221
- }, paddingX: "none", paddingY: "xs", justify: "between", className: "w-full text-left group", "aria-expanded": open, children: [_jsx(Heading, { level: 3, size: "sm", weight: "semibold", color: "muted", children: "Group Settings" }), _jsx(Span, { size: "xs", className: "group-hover:text-[var(--appkit-color-text-muted)] dark:group-hover:text-[var(--appkit-color-text-faint)] transition-colors", color: "faint", children: open ? "▲" : "▼" })] }), open && (_jsxs(Stack, { gap: "sm", className: `mt-3 ${__P.p4}`, surface: "muted", rounded: "lg", border: "default", children: [!groupId && !groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Group related listings together \u2014 e.g. a set, bundle, or multi-part item. Parts can be sold individually but shown together." }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: startGroup, isLoading: loading, children: "Start a group" })] })), isGroupParent && groupId && (_jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "start", gap: "sm", wrap: true, children: [_jsx(Div, { className: "flex-1 min-w-[200px]", children: _jsx(FormField, { name: "groupTitle", label: "Group title", type: "text", value: editTitle, onChange: setEditTitle, placeholder: "e.g. Human Toy Complete Set" }) }), _jsx(Div, { padding: "t-lg", children: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: saveTitle, isLoading: loading, children: "Save title" }) })] }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-2", color: "muted", size: "xs", weight: "semibold", children: ["Members (", childSlugsCount + 1, " \u2014 including this listing)"] }), loading && !children ? (_jsx(Text, { size: "xs", color: "faint", children: "Loading\u2026" })) : (_jsxs(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", children: [_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [_jsx(Span, { padding: "pill-2xs", weight: "semibold", className: "bg-[var(--appkit-color-primary)]/10 text-[var(--appkit-color-primary)] text-[10px]", rounded: "default", children: "Parent" }), _jsx(Text, { className: "flex-1", color: "primary", size: "sm", children: productSlug })] }), (children ?? []).filter((c) => c.id !== productId).map((child) => (_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [child.images?.[0] ? (_jsx(Div, { className: "relative w-8 h-8 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "full", overflow: "hidden", children: _jsx(MediaImage, { src: child.images[0], alt: child.title, size: "thumbnail" }) })) : (_jsx(Div, { className: "w-8 h-8", surface: "subtle", rounded: "full" })), _jsx(Text, { className: "flex-1 truncate", color: "primary", size: "sm", children: child.title }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => requestUnlinkChild(child.id), isLoading: loading, className: `${CLS_DELETE_LINK} text-[length:var(--appkit-text-xs)]`, children: "Unlink" })] }, child.id)))] }))] }), _jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setShowAddModal(true), children: "Add child listing" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestDissolveGroup, isLoading: loading, className: CLS_DELETE_LINK, children: "Dissolve group" })] })] })), !isGroupParent && groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Part of:", " ", _jsx(Span, { weight: "medium", color: "primary", children: groupTitle ?? groupParentSlug })] }), _jsxs(Text, { size: "xs", color: "muted", children: ["Parent listing: ", _jsx(Code, { className: "font-mono", children: groupParentSlug })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestLeaveGroup, isLoading: loading, className: `${CLS_DELETE_LINK} w-fit`, children: "Leave group" })] }))] })), (groupChildSlugs?.length ?? 0) >= 4 ? (_jsx(SideDrawer, { isOpen: showAddModal, onClose: () => setShowAddModal(false), title: "Add child listing", children: _jsx(AddChildContent, { addTab: addTab, setAddTab: setAddTab, createForm: createForm, setCreateForm: setCreateForm, productSlug: productSlug, storeProductsEndpoint: storeProductsEndpoint, linkTargets: linkTargets, setLinkTargets: setLinkTargets, onAddCreate: addCreateChild, onAddLink: addLinkChild, loading: loading }) })) : (_jsx(Modal, { open: showAddModal, onClose: () => setShowAddModal(false), title: "Add child listing", size: "lg", children: _jsx(AddChildContent, { addTab: addTab, setAddTab: setAddTab, createForm: createForm, setCreateForm: setCreateForm, productSlug: productSlug, storeProductsEndpoint: storeProductsEndpoint, linkTargets: linkTargets, setLinkTargets: setLinkTargets, onAddCreate: addCreateChild, onAddLink: addLinkChild, loading: loading }) })), confirmAction && (_jsx(ConfirmDeleteModal, { isOpen: true, title: confirmAction.title, message: confirmAction.message, onConfirm: confirmAction.onConfirm, onClose: () => setConfirmAction(null), isDeleting: loading }))] }));
238
+ }, paddingX: "none", paddingY: "xs", justify: "between", className: "w-full text-left group", "aria-expanded": open, children: [_jsx(Heading, { level: 3, size: "sm", weight: "semibold", color: "muted", children: "Group Settings" }), _jsx(Span, { size: "xs", className: "group-hover:text-[var(--appkit-color-text-muted)] dark:group-hover:text-[var(--appkit-color-text-faint)] transition-colors", color: "faint", children: open ? "▲" : "▼" })] }), open && (_jsxs(Stack, { gap: "sm", className: `mt-3 ${__P.p4}`, surface: "muted", rounded: "lg", border: "default", children: [!groupId && !groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Group related listings together \u2014 e.g. a set, bundle, or multi-part item. Parts can be sold individually but shown together." }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: startGroup, isLoading: loading, children: "Start a group" })] })), isGroupParent && groupId && (_jsxs(Stack, { gap: "md", children: [_jsxs(FormShellContext.Provider, { value: titleShellCtx, children: [_jsxs(Row, { align: "start", gap: "sm", wrap: true, children: [_jsx(Div, { className: "flex-1 min-w-[200px]", children: _jsx(FormField, { name: "groupTitle", label: "Group title", type: "text", value: editTitle, onChange: setEditTitle, placeholder: "e.g. Human Toy Complete Set" }) }), _jsx(Div, { padding: "t-lg", children: _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: saveTitle, isLoading: loading, children: "Save title" }) })] }), _jsx(FormErrorSummary, {})] }), _jsxs(Div, { children: [_jsxs(Text, { className: "mb-2", color: "muted", size: "xs", weight: "semibold", children: ["Members (", childSlugsCount + 1, " \u2014 including this listing)"] }), loading && !children ? (_jsx(Text, { size: "xs", color: "faint", children: "Loading\u2026" })) : (_jsxs(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", children: [_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [_jsx(Span, { padding: "pill-2xs", weight: "semibold", className: "bg-[var(--appkit-color-primary)]/10 text-[var(--appkit-color-primary)] text-[10px]", rounded: "default", children: "Parent" }), _jsx(Text, { className: "flex-1", color: "primary", size: "sm", children: productSlug })] }), (children ?? []).filter((c) => c.id !== productId).map((child) => (_jsxs(Row, { align: "center", gap: "sm", padding: "y-xs", children: [child.images?.[0] ? (_jsx(Div, { className: "relative w-8 h-8 flex-shrink-0 border border-[var(--appkit-color-border)]", rounded: "full", overflow: "hidden", children: _jsx(MediaImage, { src: child.images[0], alt: child.title, size: "thumbnail" }) })) : (_jsx(Div, { className: "w-8 h-8", surface: "subtle", rounded: "full" })), _jsx(Text, { className: "flex-1 truncate", color: "primary", size: "sm", children: child.title }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => requestUnlinkChild(child.id), isLoading: loading, className: `${CLS_DELETE_LINK} text-[length:var(--appkit-text-xs)]`, children: "Unlink" })] }, child.id)))] }))] }), _jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setShowAddModal(true), children: "Add child listing" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestDissolveGroup, isLoading: loading, className: CLS_DELETE_LINK, children: "Dissolve group" })] })] })), !isGroupParent && groupParentSlug && (_jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Part of:", " ", _jsx(Span, { weight: "medium", color: "primary", children: groupTitle ?? groupParentSlug })] }), _jsxs(Text, { size: "xs", color: "muted", children: ["Parent listing: ", _jsx(Code, { className: "font-mono", children: groupParentSlug })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: requestLeaveGroup, isLoading: loading, className: `${CLS_DELETE_LINK} w-fit`, children: "Leave group" })] }))] })), (groupChildSlugs?.length ?? 0) >= 4 ? (_jsx(SideDrawer, { isOpen: showAddModal, onClose: () => setShowAddModal(false), title: "Add child listing", children: _jsx(AddChildContent, { addTab: addTab, setAddTab: setAddTab, createForm: createForm, setCreateForm: setCreateForm, productSlug: productSlug, storeProductsEndpoint: storeProductsEndpoint, linkTargets: linkTargets, setLinkTargets: setLinkTargets, onAddCreate: addCreateChild, onAddLink: addLinkChild, loading: loading }) })) : (_jsx(Modal, { open: showAddModal, onClose: () => setShowAddModal(false), title: "Add child listing", size: "lg", children: _jsx(AddChildContent, { addTab: addTab, setAddTab: setAddTab, createForm: createForm, setCreateForm: setCreateForm, productSlug: productSlug, storeProductsEndpoint: storeProductsEndpoint, linkTargets: linkTargets, setLinkTargets: setLinkTargets, onAddCreate: addCreateChild, onAddLink: addLinkChild, loading: loading }) })), confirmAction && (_jsx(ConfirmDeleteModal, { isOpen: true, title: confirmAction.title, message: confirmAction.message, onConfirm: confirmAction.onConfirm, onClose: () => setConfirmAction(null), isDeleting: loading }))] }));
222
239
  }
223
240
  function AddChildContent({ addTab, setAddTab, createForm, setCreateForm, productSlug, storeProductsEndpoint, linkTargets, setLinkTargets, onAddCreate, onAddLink, loading, }) {
224
- return (_jsx(Stack, { gap: "md", children: _jsxs(Tabs, { value: addTab, onChange: (v) => setAddTab(v), children: [_jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "create", children: "Create new child" }), _jsx(TabsTrigger, { value: "link", children: "Link existing" })] }), _jsx(TabsContent, { value: "create", children: _jsxs(Stack, { gap: "sm", className: "mt-4", children: [_jsx(FormField, { name: "childTitle", label: "Title *", type: "text", value: createForm.title, onChange: (v) => setCreateForm({ ...createForm, title: v }), placeholder: `${productSlug}-part` }), _jsx(FormField, { name: "childPrice", label: "Price (\u20B9) *", type: "number", value: createForm.price, onChange: (v) => setCreateForm({ ...createForm, price: v }), placeholder: "0" }), _jsx(Select, { label: "Condition", value: createForm.condition, onValueChange: (v) => setCreateForm({ ...createForm, condition: v }), options: CONDITION_OPTIONS }), _jsx(Text, { className: "dark:text-[var(--appkit-color-text-faint)]/80", color: "faint", size: "xs", children: "Other fields (category, brand, shipping, return policy) are inherited from this parent listing. Need more control? Edit the full listing after saving." }), _jsx(Button, { type: "button", onClick: onAddCreate, isLoading: loading, disabled: !createForm.title || !createForm.price, children: "Create and link child" })] }) }), _jsx(TabsContent, { value: "link", children: _jsxs(Stack, { gap: "sm", className: "mt-4", children: [_jsx(Text, { size: "xs", color: "muted", children: "Search your existing products or pre-orders. Auctions cannot be linked. Select multiple to bulk-link." }), _jsx(ProductInlineSelect, { scope: "store", endpoint: storeProductsEndpoint, filters: "listingType==standard", multiple: true, value: linkTargets, onChange: setLinkTargets, placeholder: "Search listings\u2026" }), _jsx(Button, { type: "button", onClick: onAddLink, isLoading: loading, disabled: linkTargets.length === 0, children: linkTargets.length > 1 ? `Link ${linkTargets.length} to group` : "Link to group" })] }) })] }) }));
241
+ const { shellCtx, validate } = useFormShellState(createChildSchema);
242
+ useEffect(() => {
243
+ validate(createForm);
244
+ // eslint-disable-next-line react-hooks/exhaustive-deps
245
+ }, [createForm, validate]);
246
+ return (_jsx(Stack, { gap: "md", children: _jsxs(Tabs, { value: addTab, onChange: (v) => setAddTab(v), children: [_jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "create", children: "Create new child" }), _jsx(TabsTrigger, { value: "link", children: "Link existing" })] }), _jsx(TabsContent, { value: "create", children: _jsx(FormShellContext.Provider, { value: shellCtx, children: _jsxs(Stack, { gap: "sm", className: "mt-4", children: [_jsx(FormField, { name: "title", label: "Title *", type: "text", value: createForm.title, onChange: (v) => setCreateForm({ ...createForm, title: v }), placeholder: `${productSlug}-part` }), _jsx(FormField, { name: "price", label: "Price (\u20B9) *", type: "number", value: createForm.price, onChange: (v) => setCreateForm({ ...createForm, price: v }), placeholder: "0" }), _jsx(Select, { label: "Condition", value: createForm.condition, onValueChange: (v) => setCreateForm({ ...createForm, condition: v }), options: CONDITION_OPTIONS }), _jsx(Text, { className: "dark:text-[var(--appkit-color-text-faint)]/80", color: "faint", size: "xs", children: "Other fields (category, brand, shipping, return policy) are inherited from this parent listing. Need more control? Edit the full listing after saving." }), _jsx(FormErrorSummary, {}), _jsx(Button, { type: "button", onClick: onAddCreate, isLoading: loading, disabled: !createForm.title || !createForm.price, children: "Create and link child" })] }) }) }), _jsx(TabsContent, { value: "link", children: _jsxs(Stack, { gap: "sm", className: "mt-4", children: [_jsx(Text, { size: "xs", color: "muted", children: "Search your existing products or pre-orders. Auctions cannot be linked. Select multiple to bulk-link." }), _jsx(ProductInlineSelect, { scope: "store", endpoint: storeProductsEndpoint, filters: "listingType==standard", multiple: true, value: linkTargets, onChange: setLinkTargets, placeholder: "Search listings\u2026" }), _jsx(Button, { type: "button", onClick: onAddLink, isLoading: loading, disabled: linkTargets.length === 0, children: linkTargets.length > 1 ? `Link ${linkTargets.length} to group` : "Link to group" })] }) })] }) }));
225
247
  }
@@ -128,5 +128,5 @@ export async function PrizeDrawDetailPageView({ id, initialPrizeDraw, currentUse
128
128
  price: pricePerEntry,
129
129
  storeId: typeof p.storeId === "string" ? p.storeId : undefined,
130
130
  storeName: storeName ?? undefined,
131
- } }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs("nav", { "aria-label": "Breadcrumb", className: "flex items-center gap-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text-muted)] flex-wrap", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "hover:text-primary-600 transition-colors", children: "Prize Draws" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => (_jsx(PrizeDrawCollage, { items: items, hideWonState: true })), renderInfo: () => (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: "Prize Draw" }), _jsx(Span, { size: "xs", weight: "semibold", className: `inline-block ${statusClass(revealStatus)}`, padding: "pill-sm", rounded: "full", children: statusLabel(revealStatus) }), maxPerUser !== null && (_jsxs(Span, { size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", surface: "subtle", color: "muted", children: ["Limit: ", maxPerUser, " entries per customer"] })), maxPerUser !== null && userEntriesUsed !== null && (_jsxs(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: ["You have used ", userEntriesUsed, "/", maxPerUser] }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsx(Div, { className: `${__P.p4}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Entries" }), _jsxs(Text, { size: "sm", weight: "semibold", children: [current, " / ", max, " (", remaining, " left)"] })] }), revealStart && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window opens" }), _jsx(Text, { size: "sm", weight: "medium", children: revealStart.toLocaleString() })] })), revealEnd && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window closes" }), _jsx(Text, { size: "sm", weight: "medium", children: revealEnd.toLocaleString() })] }))] }) }), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined })), renderBuyBar: () => (_jsx(Div, { padding: "5", id: "prize-draw-buy-bar", border: "subtle", surface: "muted", rounded: "xl", children: _jsx(PrizeDrawEntryActions, { productId: String(product.id), productSlug: slug, title: title, thumb: thumb, pricePerEntry: pricePerEntry, currency: currency, remainingEntries: remaining, revealStatus: revealStatus, prizeGithubFileUrl: githubUrl, storeId: typeof p.storeId === "string" ? p.storeId : undefined, storeName: storeName ?? undefined }) })), renderRelated: () => (_jsxs(Stack, { gap: "xl", children: [_jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName, brandLabel: brand, storeLabel: storeName ?? undefined })] })) }), _jsx(PrizeDrawBottomActions, { pricePerEntry: pricePerEntry, currency: currency, closed: revealStatus === "closed" || remaining === 0 })] })] }));
131
+ } }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs("nav", { "aria-label": "Breadcrumb", className: "flex items-center gap-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text-muted)] flex-wrap", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "hover:text-primary-600 transition-colors", children: "Prize Draws" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => (_jsx(PrizeDrawCollage, { items: items, hideWonState: true })), renderInfo: () => (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: "Prize Draw" }), _jsx(Span, { size: "xs", weight: "semibold", className: `inline-block ${statusClass(revealStatus)}`, padding: "pill-sm", rounded: "full", children: statusLabel(revealStatus) }), maxPerUser !== null && (_jsxs(Span, { size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", surface: "subtle", color: "muted", children: ["Limit: ", maxPerUser, " entries per customer"] })), maxPerUser !== null && userEntriesUsed !== null && (_jsxs(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: ["You have used ", userEntriesUsed, "/", maxPerUser] }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsx(Div, { className: `${__P.p4}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Entries" }), _jsxs(Text, { size: "sm", weight: "semibold", children: [current, " / ", max, " (", remaining, " left)"] })] }), revealStart && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window opens" }), _jsx(Text, { size: "sm", weight: "medium", children: revealStart.toLocaleString() })] })), revealEnd && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window closes" }), _jsx(Text, { size: "sm", weight: "medium", children: revealEnd.toLocaleString() })] }))] }) }), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined })), renderBuyBar: () => (_jsx(Div, { padding: "5", id: "prize-draw-buy-bar", border: "subtle", surface: "muted", rounded: "xl", children: _jsx(PrizeDrawEntryActions, { productId: String(product.id), productSlug: slug, title: title, pricePerEntry: pricePerEntry, currency: currency, remainingEntries: remaining, revealStatus: revealStatus, prizeGithubFileUrl: githubUrl }) })), renderRelated: () => (_jsxs(Stack, { gap: "xl", children: [_jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName, brandLabel: brand, storeLabel: storeName ?? undefined })] })) }), _jsx(PrizeDrawBottomActions, { pricePerEntry: pricePerEntry, currency: currency, closed: revealStatus === "closed" || remaining === 0 })] })] }));
132
132
  }
@@ -2,14 +2,11 @@ export interface PrizeDrawEntryActionsProps {
2
2
  productId: string;
3
3
  productSlug?: string;
4
4
  title: string;
5
- thumb?: string;
6
5
  pricePerEntry: number;
7
6
  currency: string;
8
7
  remainingEntries: number;
9
8
  revealStatus: "pending" | "open" | "closed" | undefined;
10
9
  prizeGithubFileUrl?: string;
11
- storeId?: string;
12
- storeName?: string;
13
10
  }
14
11
  /**
15
12
  * Client buy panel for a prize-draw detail page (SB4-G).
@@ -18,4 +15,4 @@ export interface PrizeDrawEntryActionsProps {
18
15
  * - On confirm → add 1 entry to guest cart and route to /user/cart
19
16
  * - "View RNG source" link → prizeGithubFileUrl
20
17
  */
21
- export declare function PrizeDrawEntryActions({ productId, productSlug, title, thumb: _thumb, pricePerEntry, currency, remainingEntries, revealStatus, prizeGithubFileUrl, storeId: _storeId, storeName: _storeName, }: PrizeDrawEntryActionsProps): import("react").JSX.Element;
18
+ export declare function PrizeDrawEntryActions({ productId, productSlug, title, pricePerEntry, currency, remainingEntries, revealStatus, prizeGithubFileUrl, }: PrizeDrawEntryActionsProps): import("react").JSX.Element;
@@ -16,7 +16,7 @@ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
16
16
  * - On confirm → add 1 entry to guest cart and route to /user/cart
17
17
  * - "View RNG source" link → prizeGithubFileUrl
18
18
  */
19
- export function PrizeDrawEntryActions({ productId, productSlug, title, thumb: _thumb, pricePerEntry, currency, remainingEntries, revealStatus, prizeGithubFileUrl, storeId: _storeId, storeName: _storeName, }) {
19
+ export function PrizeDrawEntryActions({ productId, productSlug, title, pricePerEntry, currency, remainingEntries, revealStatus, prizeGithubFileUrl, }) {
20
20
  const router = useRouter();
21
21
  const { requireAuth, modalOpen, modalMessage, closeModal } = useAuthGate();
22
22
  const [consentOpen, setConsentOpen] = useState(false);
@@ -1,6 +1,5 @@
1
1
  export interface ProductDetailActionsProps {
2
2
  productId: string;
3
- productSlug: string;
4
3
  productTitle: string;
5
4
  productImage?: string;
6
5
  price?: number;
@@ -22,4 +21,4 @@ export interface ProductDetailActionsProps {
22
21
  * to the server APIs with guest-fallback. Replaces the previously-unwired
23
22
  * placeholder buttons inside ProductDetailPageView.
24
23
  */
25
- export declare function ProductDetailActions({ productId, productSlug: _productSlug, productTitle, productImage, price, currency, storeId, storeName, inStock, variant, }: ProductDetailActionsProps): import("react").JSX.Element;
24
+ export declare function ProductDetailActions({ productId, productTitle, productImage, price, currency, storeId, storeName, inStock, variant, }: ProductDetailActionsProps): import("react").JSX.Element;
@@ -19,7 +19,7 @@ import { normalizeError } from "../../../errors/normalize";
19
19
  * to the server APIs with guest-fallback. Replaces the previously-unwired
20
20
  * placeholder buttons inside ProductDetailPageView.
21
21
  */
22
- export function ProductDetailActions({ productId, productSlug: _productSlug, productTitle, productImage, price, currency, storeId, storeName, inStock, variant = "desktop", }) {
22
+ export function ProductDetailActions({ productId, productTitle, productImage, price, currency, storeId, storeName, inStock, variant = "desktop", }) {
23
23
  const router = useRouter();
24
24
  const { showToast } = useToast();
25
25
  const { requireAuth, modalOpen, modalMessage, closeModal } = useAuthGate();
@@ -2,6 +2,8 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import Link from "next/link";
5
+ import { useRouter } from "next/navigation";
6
+ import { ROUTES } from "../../../next";
5
7
  import { BaseListingCard, Button, Div, Grid, PriceDisplay, Row, Span, Stack, Text } from "../../../ui";
6
8
  import { MediaImage } from "../../media/MediaImage";
7
9
  import { formatCurrency } from "../../../utils/number.formatter";
@@ -37,6 +39,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
37
39
  ? Math.round(((product.originalPrice - product.price) / product.originalPrice) *
38
40
  100)
39
41
  : null;
42
+ const router = useRouter();
40
43
  const listingPlugin = pluginFor(normalizeListingType(product));
41
44
  const typeBadge = listingPlugin.badge
42
45
  ? { label: listingPlugin.badge.label, cls: listingPlugin.badge.className }
@@ -86,7 +89,18 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
86
89
  const MAX_CHIPS = 3;
87
90
  const visible = categories.slice(0, MAX_CHIPS);
88
91
  const overflow = Math.max(0, categories.length - MAX_CHIPS);
89
- 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.125rem] text-[10px]", 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]", 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] }))] }));
92
+ 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.125rem] text-[10px]", 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] ${product.brandSlug ? "cursor-pointer hover:underline" : ""}`, rounded: "full", surface: "subtle", color: "muted", ...(product.brandSlug
93
+ ? {
94
+ onClick: (e) => {
95
+ // The whole card is already wrapped in a <Link> — a nested
96
+ // <a> here would be invalid HTML, so this navigates via
97
+ // stopPropagation + router.push instead of a real Link.
98
+ e.preventDefault();
99
+ e.stopPropagation();
100
+ router.push(String(ROUTES.PUBLIC.BRAND_DETAIL(product.brandSlug)));
101
+ },
102
+ }
103
+ : {}), 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] }))] }));
90
104
  })(), (() => {
91
105
  const seller = safeDisplayName(product.storeName, "");
92
106
  return seller ? (_jsxs(Text, { className: "mt-0.5 text-[11px]", color: "faint", children: ["by ", seller] })) : null;
@@ -400,4 +400,5 @@ export declare const SELLER_BULK_ACTIONS: {
400
400
  readonly storeCategories: readonly ["row-activate", "row-deactivate", "row-delete"];
401
401
  readonly groupedListings: readonly ["row-delete"];
402
402
  readonly offers: readonly ["row-approve", "row-reject"];
403
+ readonly reviews: readonly ["row-reply"];
403
404
  };
@@ -566,4 +566,5 @@ export const SELLER_BULK_ACTIONS = {
566
566
  storeCategories: [ROW_ACTION_ID.ACTIVATE, ROW_ACTION_ID.DEACTIVATE, ROW_ACTION_ID.DELETE],
567
567
  groupedListings: [ROW_ACTION_ID.DELETE],
568
568
  offers: [ROW_ACTION_ID.APPROVE, ROW_ACTION_ID.REJECT],
569
+ reviews: [ROW_ACTION_ID.REPLY],
569
570
  };
@@ -76,6 +76,7 @@ export declare const productItemSchema: z.ZodObject<{
76
76
  thumbnailUrl: z.ZodOptional<z.ZodString>;
77
77
  source: z.ZodOptional<z.ZodEnum<["upload", "youtube", "external"]>>;
78
78
  youtubeId: z.ZodOptional<z.ZodString>;
79
+ duration: z.ZodOptional<z.ZodNumber>;
79
80
  }, "strip", z.ZodTypeAny, {
80
81
  type: "video" | "image" | "file";
81
82
  url: string;
@@ -83,6 +84,7 @@ export declare const productItemSchema: z.ZodObject<{
83
84
  alt?: string | undefined;
84
85
  thumbnailUrl?: string | undefined;
85
86
  youtubeId?: string | undefined;
87
+ duration?: number | undefined;
86
88
  }, {
87
89
  type: "video" | "image" | "file";
88
90
  url: string;
@@ -90,6 +92,7 @@ export declare const productItemSchema: z.ZodObject<{
90
92
  alt?: string | undefined;
91
93
  thumbnailUrl?: string | undefined;
92
94
  youtubeId?: string | undefined;
95
+ duration?: number | undefined;
93
96
  }>, "many">>;
94
97
  video: z.ZodOptional<z.ZodObject<{
95
98
  url: z.ZodString;
@@ -445,6 +448,7 @@ export declare const productItemSchema: z.ZodObject<{
445
448
  alt?: string | undefined;
446
449
  thumbnailUrl?: string | undefined;
447
450
  youtubeId?: string | undefined;
451
+ duration?: number | undefined;
448
452
  }[] | undefined;
449
453
  inStock?: boolean | undefined;
450
454
  rating?: number | undefined;
@@ -583,6 +587,7 @@ export declare const productItemSchema: z.ZodObject<{
583
587
  alt?: string | undefined;
584
588
  thumbnailUrl?: string | undefined;
585
589
  youtubeId?: string | undefined;
590
+ duration?: number | undefined;
586
591
  }[] | undefined;
587
592
  inStock?: boolean | undefined;
588
593
  rating?: number | undefined;
@@ -2,9 +2,7 @@ import React from "react";
2
2
  export interface CouponsIndexListingProps {
3
3
  /** Pre-fetched coupons to show on first render */
4
4
  initialCoupons?: any[];
5
- /** If set, only show coupons from this store (slug, for display) */
6
- storeSlug?: string;
7
5
  /** If set, only show coupons from this store (id, for filtering) */
8
6
  storeId?: string;
9
7
  }
10
- export declare function CouponsIndexListing({ initialCoupons, storeSlug: _storeSlug, storeId, }: CouponsIndexListingProps): React.JSX.Element;
8
+ export declare function CouponsIndexListing({ initialCoupons, storeId, }: CouponsIndexListingProps): React.JSX.Element;
@@ -28,7 +28,7 @@ const COUPON_TYPES = [
28
28
  { value: COUPON_FIELDS.TYPE_VALUES.BUY_X_GET_Y, label: "Buy X Get Y" },
29
29
  ];
30
30
  const FILTER_KEYS = [TABLE_KEYS.TYPE, TABLE_KEYS.DATE_FROM, TABLE_KEYS.DATE_TO];
31
- export function CouponsIndexListing({ initialCoupons, storeSlug: _storeSlug, storeId, }) {
31
+ export function CouponsIndexListing({ initialCoupons, storeId, }) {
32
32
  const table = useUrlTable({ defaults: { pageSize: "12", sort: DEFAULT_SORT } });
33
33
  const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
34
34
  const [filterOpen, setFilterOpen] = useState(false);
@@ -4,8 +4,6 @@ export interface SearchViewProps {
4
4
  query?: string;
5
5
  /** Total result count */
6
6
  total: number;
7
- /** Whether data is loading */
8
- isLoading: boolean;
9
7
  labels?: {
10
8
  searchTitle?: string;
11
9
  resultsCount?: (count: number, query: string) => string;
@@ -26,4 +24,4 @@ export interface SearchViewProps {
26
24
  renderPagination?: () => React.ReactNode;
27
25
  className?: string;
28
26
  }
29
- export declare function SearchView({ query, total, isLoading: _isLoading, labels, renderSearchInput, renderFilters, renderActiveFilters, renderToolbar, renderResults, renderPagination, className, }: SearchViewProps): React.JSX.Element;
27
+ export declare function SearchView({ query, total, labels, renderSearchInput, renderFilters, renderActiveFilters, renderToolbar, renderResults, renderPagination, className, }: SearchViewProps): React.JSX.Element;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Div, Heading, Main, Row, Span, Stack, Text } from "../../../ui";
3
- export function SearchView({ query, total, isLoading: _isLoading, labels = {}, renderSearchInput, renderFilters, renderActiveFilters, renderToolbar, renderResults, renderPagination, className = "", }) {
3
+ export function SearchView({ query, total, labels = {}, renderSearchInput, renderFilters, renderActiveFilters, renderToolbar, renderResults, renderPagination, className = "", }) {
4
4
  const hasQuery = !!query?.trim();
5
5
  return (_jsx(Main, { className: `min-h-screen ${className}`, children: _jsxs(Stack, { padding: "y-lg", gap: "md", children: [_jsx(Div, { children: renderSearchInput() }), hasQuery && (_jsx(Div, { children: _jsx(Heading, { level: 1, size: "xl", weight: "semibold", children: labels.resultsCount
6
6
  ? labels.resultsCount(total, query)
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Row } from "@mohasinac/appkit/ui";
4
4
  import { useState } from "react";
5
5
  import { Alert, Button, Div, FormField, Stack, Text } from "../../../ui";
6
+ import { FormErrorSummary } from "../../../ui/forms";
6
7
  const __P = {
7
8
  p5: "p-[var(--appkit-space-5)]",
8
9
  };
@@ -50,5 +51,5 @@ export function QuickProductForm({ values, onChange, onPublish, onSave, onSwitch
50
51
  return (_jsxs(Stack, { gap: "lg", className: `${__P.p5}`, children: [_jsx(Div, { children: _jsx(Text, { size: "sm", color: "muted", children: "Quick add \u2014 fill the essentials and publish. You can add more details later." }) }), touched && Object.keys(errors).length > 0 && (_jsx(Alert, { variant: "error", children: "Please fix the highlighted fields before publishing." })), _jsx(FormField, { name: "title", label: "Product Name", type: "text", value: values.title ?? "", onChange: (v) => onChange({ title: v }), placeholder: "e.g. Charizard Base Set PSA 9", required: true, error: touched ? errors.title : undefined }), renderCategorySelector ? (_jsxs(Div, { children: [_jsx(Text, { className: "mb-1", color: "muted", size: "sm", weight: "medium", children: "Category" }), renderCategorySelector({
51
52
  value: values.category ?? "",
52
53
  onChange: (v) => onChange({ category: v }),
53
- }), touched && errors.category && (_jsx(Text, { className: "text-[var(--appkit-color-error)] mt-1", size: "xs", children: errors.category }))] })) : (_jsx(FormField, { name: "category", label: "Category", type: "text", value: values.category ?? "", onChange: (v) => onChange({ category: v }), placeholder: "e.g. Trading Cards", error: touched ? errors.category : undefined })), _jsx(FormField, { name: "price", label: "Price (\u20B9)", type: "number", value: toRupeesString(values.price), onChange: (v) => onChange({ price: fromRupeesString(v) }), placeholder: "e.g. 499", required: true, error: touched ? errors.price : undefined }), _jsx(FormField, { name: "mainImage", label: "Product Image", type: "image", value: values.mainImage ?? "", onChange: (v) => onChange({ mainImage: v }), onUpload: onUploadImage, required: true, error: touched ? errors.mainImage : undefined }), _jsx(FormField, { name: "description", label: "Description", type: "textarea", value: values.description ?? "", onChange: (v) => onChange({ description: v }), placeholder: "Brief description (optional)", rows: 3 }), _jsx(FormField, { name: "stockQuantity", label: "Stock Quantity", type: "number", value: String(values.stockQuantity ?? 1), onChange: (v) => onChange({ stockQuantity: Math.max(0, parseInt(v, 10) || 0) }), placeholder: "1", hint: "How many units are available" }), _jsxs(Stack, { gap: "3", padding: "t-xs", children: [_jsxs(Row, { gap: "3", children: [_jsx(Button, { variant: "primary", onClick: handlePublish, disabled: isLoading, className: "flex-1", children: isLoading ? "Publishing..." : "Publish" }), _jsx(Button, { variant: "secondary", onClick: handleSave, disabled: isLoading, children: "Save Draft" })] }), _jsx(Button, { variant: "ghost", size: "sm", textSize: "xs", onClick: onSwitchToFull, className: "self-center", children: "Show all fields (advanced)" })] })] }));
54
+ }), touched && errors.category && (_jsx(Text, { className: "text-[var(--appkit-color-error)] mt-1", size: "xs", children: errors.category }))] })) : (_jsx(FormField, { name: "category", label: "Category", type: "text", value: values.category ?? "", onChange: (v) => onChange({ category: v }), placeholder: "e.g. Trading Cards", error: touched ? errors.category : undefined })), _jsx(FormField, { name: "price", label: "Price (\u20B9)", type: "number", value: toRupeesString(values.price), onChange: (v) => onChange({ price: fromRupeesString(v) }), placeholder: "e.g. 499", required: true, error: touched ? errors.price : undefined }), _jsx(FormField, { name: "mainImage", label: "Product Image", type: "image", value: values.mainImage ?? "", onChange: (v) => onChange({ mainImage: v }), onUpload: onUploadImage, required: true, error: touched ? errors.mainImage : undefined }), _jsx(FormField, { name: "description", label: "Description", type: "textarea", value: values.description ?? "", onChange: (v) => onChange({ description: v }), placeholder: "Brief description (optional)", rows: 3 }), _jsx(FormField, { name: "stockQuantity", label: "Stock Quantity", type: "number", value: String(values.stockQuantity ?? 1), onChange: (v) => onChange({ stockQuantity: Math.max(0, parseInt(v, 10) || 0) }), placeholder: "1", hint: "How many units are available" }), _jsxs(Stack, { gap: "3", padding: "t-xs", children: [_jsx(FormErrorSummary, {}), _jsxs(Row, { gap: "3", children: [_jsx(Button, { variant: "primary", onClick: handlePublish, disabled: isLoading, className: "flex-1", children: isLoading ? "Publishing..." : "Publish" }), _jsx(Button, { variant: "secondary", onClick: handleSave, disabled: isLoading, children: "Save Draft" })] }), _jsx(Button, { variant: "ghost", size: "sm", textSize: "xs", onClick: onSwitchToFull, className: "self-center", children: "Show all fields (advanced)" })] })] }));
54
55
  }