@mohasinac/appkit 4.59.0 → 4.60.0

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 (531) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +62 -5
  3. package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +2 -2
  4. package/dist/_internal/server/features/brands/actions.js +78 -4
  5. package/dist/_internal/server/features/checkout/actions.d.ts +36 -13
  6. package/dist/_internal/server/features/checkout/actions.js +668 -183
  7. package/dist/_internal/server/features/checkout/supplier-identity.js +18 -1
  8. package/dist/_internal/server/features/gateway-events/index.d.ts +10 -0
  9. package/dist/_internal/server/features/gateway-events/index.js +10 -0
  10. package/dist/_internal/server/features/gateway-events/ingest.d.ts +127 -0
  11. package/dist/_internal/server/features/gateway-events/ingest.js +188 -0
  12. package/dist/_internal/server/features/gateway-events/redact.d.ts +66 -0
  13. package/dist/_internal/server/features/gateway-events/redact.js +151 -0
  14. package/dist/_internal/server/features/grievance/actions.d.ts +63 -0
  15. package/dist/_internal/server/features/grievance/actions.js +173 -0
  16. package/dist/_internal/server/features/grievance/index.d.ts +8 -0
  17. package/dist/_internal/server/features/grievance/index.js +8 -0
  18. package/dist/_internal/server/features/grouped/data.js +28 -3
  19. package/dist/_internal/server/features/lottery/actions.js +99 -4
  20. package/dist/_internal/server/features/order-completion/actions.d.ts +92 -0
  21. package/dist/_internal/server/features/order-completion/actions.js +336 -0
  22. package/dist/_internal/server/features/order-completion/index.d.ts +7 -0
  23. package/dist/_internal/server/features/order-completion/index.js +7 -0
  24. package/dist/_internal/server/features/orders/actions.d.ts +13 -0
  25. package/dist/_internal/server/features/orders/actions.js +56 -2
  26. package/dist/_internal/server/features/orders/adapters.js +26 -0
  27. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +116 -0
  28. package/dist/_internal/server/features/orders/cancellation-refund.js +466 -0
  29. package/dist/_internal/server/features/orders/index.d.ts +2 -1
  30. package/dist/_internal/server/features/orders/index.js +1 -1
  31. package/dist/_internal/server/features/orders/service.d.ts +60 -0
  32. package/dist/_internal/server/features/orders/service.js +74 -0
  33. package/dist/_internal/server/features/payment-cases/disputes.d.ts +76 -0
  34. package/dist/_internal/server/features/payment-cases/disputes.js +241 -0
  35. package/dist/_internal/server/features/payment-cases/index.d.ts +9 -0
  36. package/dist/_internal/server/features/payment-cases/index.js +9 -0
  37. package/dist/_internal/server/features/payouts/actions.d.ts +28 -3
  38. package/dist/_internal/server/features/payouts/actions.js +84 -10
  39. package/dist/_internal/server/features/points/adjust.d.ts +61 -0
  40. package/dist/_internal/server/features/points/adjust.js +121 -0
  41. package/dist/_internal/server/features/points/award.d.ts +65 -0
  42. package/dist/_internal/server/features/points/award.js +145 -0
  43. package/dist/_internal/server/features/price-index/market.d.ts +33 -0
  44. package/dist/_internal/server/features/price-index/market.js +54 -1
  45. package/dist/_internal/server/features/products/data.js +40 -22
  46. package/dist/_internal/server/features/protection-claims/actions.d.ts +72 -0
  47. package/dist/_internal/server/features/protection-claims/actions.js +228 -0
  48. package/dist/_internal/server/features/protection-claims/index.d.ts +8 -0
  49. package/dist/_internal/server/features/protection-claims/index.js +8 -0
  50. package/dist/_internal/server/features/refunds/actions.d.ts +20 -0
  51. package/dist/_internal/server/features/refunds/actions.js +259 -17
  52. package/dist/_internal/server/features/refunds/capacity.d.ts +29 -0
  53. package/dist/_internal/server/features/refunds/capacity.js +37 -0
  54. package/dist/_internal/server/features/reviews/actions.js +3 -2
  55. package/dist/_internal/server/features/search/index-build/sources.js +20 -1
  56. package/dist/_internal/server/features/shipping/reconcile.d.ts +10 -1
  57. package/dist/_internal/server/features/shipping/reconcile.js +34 -3
  58. package/dist/_internal/server/features/shipping/reimbursement.d.ts +117 -0
  59. package/dist/_internal/server/features/shipping/reimbursement.js +223 -0
  60. package/dist/_internal/server/features/stores/tabs.d.ts +19 -4
  61. package/dist/_internal/server/features/stores/tabs.js +24 -4
  62. package/dist/_internal/server/functions/https.d.ts +31 -1
  63. package/dist/_internal/server/functions/https.js +52 -1
  64. package/dist/_internal/server/functions/scheduled.d.ts +72 -1
  65. package/dist/_internal/server/functions/scheduled.js +124 -1
  66. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +62 -16
  67. package/dist/_internal/server/jobs/core/boxRollupReconcile.d.ts +46 -0
  68. package/dist/_internal/server/jobs/core/boxRollupReconcile.js +142 -0
  69. package/dist/_internal/server/jobs/core/dailyDataCleanup.js +149 -1
  70. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +14 -0
  71. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +79 -1
  72. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  73. package/dist/_internal/server/jobs/core/index.js +2 -0
  74. package/dist/_internal/server/jobs/core/marketPriceRollup.d.ts +64 -0
  75. package/dist/_internal/server/jobs/core/marketPriceRollup.js +153 -0
  76. package/dist/_internal/server/jobs/core/obligationSweep.d.ts +36 -0
  77. package/dist/_internal/server/jobs/core/obligationSweep.js +503 -0
  78. package/dist/_internal/server/jobs/core/paymentReconcile.d.ts +79 -0
  79. package/dist/_internal/server/jobs/core/paymentReconcile.js +614 -0
  80. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +34 -0
  81. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +35 -4
  82. package/dist/_internal/server/jobs/handlers/boxRollupReconcile.d.ts +2 -0
  83. package/dist/_internal/server/jobs/handlers/boxRollupReconcile.js +15 -0
  84. package/dist/_internal/server/jobs/handlers/countersReconcileNow.d.ts +65 -0
  85. package/dist/_internal/server/jobs/handlers/countersReconcileNow.js +89 -0
  86. package/dist/_internal/server/jobs/handlers/index.d.ts +5 -0
  87. package/dist/_internal/server/jobs/handlers/index.js +5 -0
  88. package/dist/_internal/server/jobs/handlers/marketPriceRollup.d.ts +2 -0
  89. package/dist/_internal/server/jobs/handlers/marketPriceRollup.js +2 -0
  90. package/dist/_internal/server/jobs/handlers/obligationSweep.d.ts +2 -0
  91. package/dist/_internal/server/jobs/handlers/obligationSweep.js +15 -0
  92. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +30 -1
  93. package/dist/_internal/server/jobs/handlers/paymentReconcile.d.ts +2 -0
  94. package/dist/_internal/server/jobs/handlers/paymentReconcile.js +6 -0
  95. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  96. package/dist/_internal/shared/actions/action-registry.js +71 -0
  97. package/dist/_internal/shared/checkout/coupon-discount.d.ts +73 -0
  98. package/dist/_internal/shared/checkout/coupon-discount.js +103 -0
  99. package/dist/_internal/shared/checkout/lanes.d.ts +42 -0
  100. package/dist/_internal/shared/checkout/lanes.js +46 -0
  101. package/dist/_internal/shared/checkout/order-math.d.ts +149 -1
  102. package/dist/_internal/shared/checkout/order-math.js +251 -3
  103. package/dist/_internal/shared/checkout/refundable-base.d.ts +116 -0
  104. package/dist/_internal/shared/checkout/refundable-base.js +122 -0
  105. package/dist/_internal/shared/features/auctions/config.d.ts +14 -1
  106. package/dist/_internal/shared/features/auctions/config.js +30 -1
  107. package/dist/_internal/shared/features/brands/schema.d.ts +42 -0
  108. package/dist/_internal/shared/features/brands/schema.js +18 -0
  109. package/dist/_internal/shared/features/orders/refund-copy.d.ts +22 -0
  110. package/dist/_internal/shared/features/orders/refund-copy.js +34 -0
  111. package/dist/_internal/shared/features/print/label-profiles.d.ts +198 -0
  112. package/dist/_internal/shared/features/print/label-profiles.js +350 -0
  113. package/dist/_internal/shared/features/products/to-product-item.js +33 -5
  114. package/dist/_internal/shared/fees/calculator.d.ts +31 -2
  115. package/dist/_internal/shared/fees/calculator.js +103 -5
  116. package/dist/_internal/shared/fees/india-states.d.ts +195 -0
  117. package/dist/_internal/shared/fees/india-states.js +190 -0
  118. package/dist/_internal/shared/fees/payout-hold.d.ts +80 -0
  119. package/dist/_internal/shared/fees/payout-hold.js +74 -0
  120. package/dist/_internal/shared/obligations/deadlines.d.ts +94 -0
  121. package/dist/_internal/shared/obligations/deadlines.js +155 -0
  122. package/dist/_internal/shared/shipping/quote.d.ts +96 -0
  123. package/dist/_internal/shared/shipping/quote.js +67 -0
  124. package/dist/_internal/shared/time/business-days.d.ts +91 -0
  125. package/dist/_internal/shared/time/business-days.js +185 -0
  126. package/dist/cli/index.js +0 -2
  127. package/dist/client.d.ts +9 -4
  128. package/dist/client.js +26 -3
  129. package/dist/configs/tailwind.d.ts +0 -12
  130. package/dist/configs/tailwind.js +28 -15
  131. package/dist/constants/api-endpoints.d.ts +51 -9
  132. package/dist/constants/api-endpoints.js +23 -7
  133. package/dist/constants/index.d.ts +1 -1
  134. package/dist/constants/index.js +1 -1
  135. package/dist/contracts/index.d.ts +1 -1
  136. package/dist/contracts/payment.d.ts +131 -0
  137. package/dist/features/about/components/AboutView.js +1 -1
  138. package/dist/features/about/components/DeveloperView.js +5 -2
  139. package/dist/features/about/components/FAQPageView.js +2 -1
  140. package/dist/features/about/components/FeesView.js +2 -1
  141. package/dist/features/about/components/HelpPageView.js +2 -1
  142. package/dist/features/about/components/HowAuctionsWorkView.js +2 -1
  143. package/dist/features/about/components/HowCheckoutWorksView.js +2 -1
  144. package/dist/features/about/components/HowEmiWorksView.js +2 -1
  145. package/dist/features/about/components/HowOffersWorkView.js +2 -1
  146. package/dist/features/about/components/HowOrdersWorkView.js +2 -1
  147. package/dist/features/about/components/HowPayoutsWorkView.js +2 -1
  148. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -1
  149. package/dist/features/about/components/HowReviewsWorkView.js +2 -1
  150. package/dist/features/about/components/PolicyPageView.js +2 -1
  151. package/dist/features/about/components/ProseHero.d.ts +73 -0
  152. package/dist/features/about/components/ProseHero.js +18 -0
  153. package/dist/features/about/components/SecurityPrivacyView.js +2 -1
  154. package/dist/features/about/components/ShippingPolicyView.js +2 -1
  155. package/dist/features/about/components/TrackOrderView.js +2 -1
  156. package/dist/features/about/components/UnauthorizedView.js +1 -1
  157. package/dist/features/about/index.d.ts +2 -0
  158. package/dist/features/about/index.js +5 -0
  159. package/dist/features/account/actions/address-actions.d.ts +26 -2
  160. package/dist/features/account/actions/address-actions.js +25 -1
  161. package/dist/features/account/components/BuyerShoppingGuideView.js +1 -1
  162. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  163. package/dist/features/account/components/UserOrdersView.js +17 -0
  164. package/dist/features/account/components/UserSidebar.js +1 -1
  165. package/dist/features/account/hooks/useNotifications.js +29 -0
  166. package/dist/features/admin/actions/admin-coupon-actions.js +36 -0
  167. package/dist/features/admin/components/AdminBeysView.js +2 -2
  168. package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
  169. package/dist/features/admin/components/AdminBrandEditorView.js +32 -2
  170. package/dist/features/admin/components/AdminBundleEditorView.js +1 -1
  171. package/dist/features/admin/components/AdminCarouselEditorView.js +1 -1
  172. package/dist/features/admin/components/AdminCategoriesView.js +1 -1
  173. package/dist/features/admin/components/AdminCategoryEditorView.js +73 -17
  174. package/dist/features/admin/components/AdminContactEditorView.js +1 -1
  175. package/dist/features/admin/components/AdminCouponEditorView.js +26 -1
  176. package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
  177. package/dist/features/admin/components/AdminFaqsView.js +2 -2
  178. package/dist/features/admin/components/AdminGatewayEventsView.d.ts +54 -0
  179. package/dist/features/admin/components/AdminGatewayEventsView.js +209 -0
  180. package/dist/features/admin/components/AdminGuideHubView.js +1 -1
  181. package/dist/features/admin/components/AdminMoneyCasesView.d.ts +60 -0
  182. package/dist/features/admin/components/AdminMoneyCasesView.js +287 -0
  183. package/dist/features/admin/components/AdminPartsView.js +2 -2
  184. package/dist/features/admin/components/AdminProductsView.js +75 -4
  185. package/dist/features/admin/components/AdminSidebar.js +2 -2
  186. package/dist/features/admin/components/AdminSiteSettingsView.js +65 -7
  187. package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
  188. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  189. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
  190. package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
  191. package/dist/features/admin/components/AdminUsersView.js +72 -1
  192. package/dist/features/admin/components/AdminViewCards.d.ts +3 -1
  193. package/dist/features/admin/components/AdminViewCards.js +4 -4
  194. package/dist/features/admin/components/DataListingView.d.ts +28 -0
  195. package/dist/features/admin/components/DataListingView.js +175 -14
  196. package/dist/features/admin/components/DataTable.d.ts +12 -1
  197. package/dist/features/admin/components/DataTable.js +3 -3
  198. package/dist/features/admin/components/OwnerQuickActions.d.ts +1 -1
  199. package/dist/features/admin/components/OwnerQuickActions.js +60 -2
  200. package/dist/features/admin/components/RecordOwnerQuickActions.d.ts +1 -1
  201. package/dist/features/admin/components/RecordOwnerQuickActions.js +61 -14
  202. package/dist/features/admin/components/analytics/AdminStatCard.d.ts +35 -1
  203. package/dist/features/admin/components/analytics/AdminStatCard.js +77 -2
  204. package/dist/features/admin/components/index.d.ts +4 -0
  205. package/dist/features/admin/components/index.js +6 -0
  206. package/dist/features/admin/constants/filter-tabs.d.ts +156 -0
  207. package/dist/features/admin/constants/filter-tabs.js +106 -0
  208. package/dist/features/admin/repository/site-settings.repository.d.ts +22 -0
  209. package/dist/features/admin/repository/site-settings.repository.js +82 -1
  210. package/dist/features/admin/schemas/admin-editor-forms.d.ts +21 -0
  211. package/dist/features/admin/schemas/admin-editor-forms.js +44 -0
  212. package/dist/features/admin/schemas/firestore.js +5 -1
  213. package/dist/features/admin/schemas/site-settings-form.js +30 -1
  214. package/dist/features/auctions/actions/bid-actions.js +13 -1
  215. package/dist/features/auctions/components/AuctionBottomActions.js +2 -2
  216. package/dist/features/auctions/components/AuctionDetailPageView.js +3 -1
  217. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -0
  218. package/dist/features/auctions/components/MarketplaceAuctionCard.js +5 -3
  219. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +8 -1
  220. package/dist/features/auctions/components/PlaceBidFormClient.js +2 -2
  221. package/dist/features/audit-log/schemas/firestore.d.ts +28 -0
  222. package/dist/features/audit-log/schemas/firestore.js +14 -0
  223. package/dist/features/auth/permissions/constants.d.ts +17 -1
  224. package/dist/features/auth/permissions/constants.js +18 -0
  225. package/dist/features/blog/components/BlogPostView.js +1 -1
  226. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
  227. package/dist/features/categories/api/[id]/description-template/route.js +107 -1
  228. package/dist/features/categories/components/BrandDetailPageView.js +2 -2
  229. package/dist/features/categories/components/BreadcrumbTrail.js +7 -1
  230. package/dist/features/categories/components/BundleDetailView.js +1 -1
  231. package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
  232. package/dist/features/categories/components/CategoryForm.js +12 -1
  233. package/dist/features/categories/components/CategoryTemplatePicker.js +38 -5
  234. package/dist/features/categories/repository/market-price-index.repository.d.ts +123 -0
  235. package/dist/features/categories/repository/market-price-index.repository.js +105 -0
  236. package/dist/features/categories/repository/price-observation.repository.d.ts +166 -0
  237. package/dist/features/categories/repository/price-observation.repository.js +132 -0
  238. package/dist/features/events/components/EventSaleBanner.js +1 -1
  239. package/dist/features/events/components/EventStatusBadge.js +1 -1
  240. package/dist/features/faq/components/FAQAccordion.js +2 -1
  241. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  242. package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
  243. package/dist/features/faq/components/RelatedFAQs.js +1 -1
  244. package/dist/features/filters/FilterFacetSection.js +1 -1
  245. package/dist/features/filters/SwitchFilter.js +1 -1
  246. package/dist/features/gateway-events/repository/gateway-events.repository.d.ts +117 -0
  247. package/dist/features/gateway-events/repository/gateway-events.repository.js +274 -0
  248. package/dist/features/gateway-events/schemas/firestore.d.ts +217 -0
  249. package/dist/features/gateway-events/schemas/firestore.js +125 -0
  250. package/dist/features/gateway-events/schemas/index.d.ts +81 -0
  251. package/dist/features/gateway-events/schemas/index.js +79 -0
  252. package/dist/features/grouped/components/GroupedListingDetailView.js +1 -1
  253. package/dist/features/homepage/components/AnnouncementBar.js +37 -1
  254. package/dist/features/homepage/components/AnnouncementBar.style.css +30 -0
  255. package/dist/features/homepage/components/BrandsSection.js +1 -1
  256. package/dist/features/homepage/components/CTABannerSection.js +1 -1
  257. package/dist/features/homepage/components/FeaturedBundlesSection.js +14 -24
  258. package/dist/features/homepage/components/HeroCarousel.js +2 -2
  259. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  260. package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +7 -0
  261. package/dist/features/inventory/components/AdminMoveLedgerView.js +157 -0
  262. package/dist/features/inventory/components/AdminStorageBoxesView.d.ts +11 -0
  263. package/dist/features/inventory/components/AdminStorageBoxesView.js +168 -0
  264. package/dist/features/inventory/components/ReceiveStationView.d.ts +39 -0
  265. package/dist/features/inventory/components/ReceiveStationView.js +413 -0
  266. package/dist/features/inventory/components/operator-message.d.ts +29 -0
  267. package/dist/features/inventory/components/operator-message.js +41 -0
  268. package/dist/features/inventory/index.d.ts +13 -0
  269. package/dist/features/inventory/index.js +28 -0
  270. package/dist/features/inventory/repository/inventory-movements.repository.d.ts +97 -0
  271. package/dist/features/inventory/repository/inventory-movements.repository.js +186 -0
  272. package/dist/features/inventory/repository/inventory-placements.repository.d.ts +179 -0
  273. package/dist/features/inventory/repository/inventory-placements.repository.js +345 -0
  274. package/dist/features/inventory/repository/storage-boxes.repository.d.ts +83 -0
  275. package/dist/features/inventory/repository/storage-boxes.repository.js +127 -0
  276. package/dist/features/inventory/schemas/firestore.d.ts +197 -0
  277. package/dist/features/inventory/schemas/firestore.js +159 -0
  278. package/dist/features/layout/AppLayoutShell.d.ts +12 -1
  279. package/dist/features/layout/AppLayoutShell.js +25 -12
  280. package/dist/features/layout/AutoBreadcrumbs.js +162 -3
  281. package/dist/features/layout/AutoBreadcrumbs.style.css +45 -0
  282. package/dist/features/layout/BottomNavbar.d.ts +1 -1
  283. package/dist/features/layout/BottomNavbar.js +2 -2
  284. package/dist/features/media/MediaAvatar.js +1 -1
  285. package/dist/features/media/MediaImage.d.ts +24 -4
  286. package/dist/features/media/MediaImage.js +44 -4
  287. package/dist/features/media/MediaLightbox.js +1 -1
  288. package/dist/features/media/modals/ImageCropModal.js +1 -1
  289. package/dist/features/media/modals/ImageEditor.js +1 -1
  290. package/dist/features/media/upload/MediaUploadField.js +91 -3
  291. package/dist/features/obligations/constants/policies.d.ts +92 -0
  292. package/dist/features/obligations/constants/policies.js +378 -0
  293. package/dist/features/obligations/repository/obligations.repository.d.ts +68 -0
  294. package/dist/features/obligations/repository/obligations.repository.js +158 -0
  295. package/dist/features/obligations/schemas/firestore.d.ts +160 -0
  296. package/dist/features/obligations/schemas/firestore.js +87 -0
  297. package/dist/features/orders/actions/order-actions.d.ts +43 -4
  298. package/dist/features/orders/actions/order-actions.js +60 -3
  299. package/dist/features/orders/actions/refund-actions.js +70 -10
  300. package/dist/features/orders/components/OrderCompletionPanel.d.ts +27 -0
  301. package/dist/features/orders/components/OrderCompletionPanel.js +192 -0
  302. package/dist/features/orders/components/OrdersList.js +2 -2
  303. package/dist/features/orders/components/RefundHistoryTable.js +3 -1
  304. package/dist/features/orders/components/index.d.ts +2 -0
  305. package/dist/features/orders/components/index.js +6 -0
  306. package/dist/features/orders/constants/transitions.d.ts +59 -0
  307. package/dist/features/orders/constants/transitions.js +104 -0
  308. package/dist/features/orders/repository/orders.repository.d.ts +109 -6
  309. package/dist/features/orders/repository/orders.repository.js +464 -21
  310. package/dist/features/orders/schemas/firestore.d.ts +270 -0
  311. package/dist/features/orders/schemas/firestore.js +24 -0
  312. package/dist/features/orders/schemas/index.d.ts +61 -0
  313. package/dist/features/orders/schemas/index.js +22 -0
  314. package/dist/features/orders/types/index.d.ts +79 -0
  315. package/dist/features/parts/components/PartsIndexPageView.js +8 -1
  316. package/dist/features/payment-cases/repository/payment-cases.repository.d.ts +170 -0
  317. package/dist/features/payment-cases/repository/payment-cases.repository.js +342 -0
  318. package/dist/features/payment-cases/schemas/firestore.d.ts +229 -0
  319. package/dist/features/payment-cases/schemas/firestore.js +105 -0
  320. package/dist/features/payment-cases/schemas/resolve-form.d.ts +97 -0
  321. package/dist/features/payment-cases/schemas/resolve-form.js +114 -0
  322. package/dist/features/payments/repository/payout.repository.d.ts +0 -1
  323. package/dist/features/payments/repository/payout.repository.js +0 -1
  324. package/dist/features/points/repository/points.repository.d.ts +122 -0
  325. package/dist/features/points/repository/points.repository.js +304 -1
  326. package/dist/features/points/schemas/adjust-form.d.ts +58 -0
  327. package/dist/features/points/schemas/adjust-form.js +63 -0
  328. package/dist/features/points/schemas/firestore.d.ts +108 -1
  329. package/dist/features/points/schemas/firestore.js +84 -0
  330. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -3
  331. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  332. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
  333. package/dist/features/price-index/components/PriceIndexToolView.d.ts +23 -4
  334. package/dist/features/price-index/components/PriceIndexToolView.js +71 -6
  335. package/dist/features/price-index/market-stats.d.ts +82 -0
  336. package/dist/features/price-index/market-stats.js +230 -0
  337. package/dist/features/print/components/BoxLabelPrintView.d.ts +25 -0
  338. package/dist/features/print/components/BoxLabelPrintView.js +66 -0
  339. package/dist/features/print/components/LabelProfilePicker.d.ts +13 -0
  340. package/dist/features/print/components/LabelProfilePicker.js +38 -0
  341. package/dist/features/print/components/labels.d.ts +117 -0
  342. package/dist/features/print/components/labels.js +258 -0
  343. package/dist/features/print/components/labels.style.css +46 -0
  344. package/dist/features/print/index.d.ts +6 -0
  345. package/dist/features/print/index.js +16 -0
  346. package/dist/features/products/columns/productTableColumns.js +5 -4
  347. package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
  348. package/dist/features/products/components/MarketplacePrizeDrawCard.js +6 -6
  349. package/dist/features/products/components/PrizeDrawCollage.js +1 -1
  350. package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -1
  351. package/dist/features/products/components/PrizeRevealModal.js +2 -2
  352. package/dist/features/products/components/ProductDetailPageView.js +18 -4
  353. package/dist/features/products/components/ProductForm.js +34 -23
  354. package/dist/features/products/components/ProductGrid.js +86 -62
  355. package/dist/features/products/constants/card-badges.d.ts +97 -0
  356. package/dist/features/products/constants/card-badges.js +100 -0
  357. package/dist/features/products/repository/products.repository.js +34 -1
  358. package/dist/features/products/schemas/firestore.d.ts +46 -3
  359. package/dist/features/products/schemas/firestore.js +21 -0
  360. package/dist/features/promotions/components/PromotionsView.js +1 -1
  361. package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +32 -0
  362. package/dist/features/promotions/repository/claimed-coupons.repository.js +58 -0
  363. package/dist/features/promotions/schemas/firestore.js +30 -3
  364. package/dist/features/promotions/schemas/index.d.ts +6 -6
  365. package/dist/features/protection-claims/repository/protection-claims.repository.d.ts +54 -0
  366. package/dist/features/protection-claims/repository/protection-claims.repository.js +174 -0
  367. package/dist/features/protection-claims/schemas/firestore.d.ts +168 -0
  368. package/dist/features/protection-claims/schemas/firestore.js +130 -0
  369. package/dist/features/reviews/actions/review-actions.js +3 -2
  370. package/dist/features/reviews/components/ReviewModal.js +1 -1
  371. package/dist/features/reviews/components/ReviewsList.js +1 -1
  372. package/dist/features/reviews/schemas/firestore.d.ts +20 -1
  373. package/dist/features/scams/constants/scam-types.d.ts +2 -0
  374. package/dist/features/scams/constants/scam-types.js +18 -0
  375. package/dist/features/scams/schemas/report-form.d.ts +3 -3
  376. package/dist/features/scams/schemas/report-form.js +26 -1
  377. package/dist/features/search/components/Search.js +9 -9
  378. package/dist/features/search/components/SearchResultsClient.js +18 -3
  379. package/dist/features/search/components/SearchResultsPageView.d.ts +1 -6
  380. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  381. package/dist/features/seller/actions/offer-actions.js +16 -1
  382. package/dist/features/seller/actions/seller-actions.js +14 -3
  383. package/dist/features/seller/components/CategoryInlineSelect.js +75 -11
  384. package/dist/features/seller/components/PrintCenterView.d.ts +5 -0
  385. package/dist/features/seller/components/PrintCenterView.js +41 -30
  386. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  387. package/dist/features/seller/components/SellerPayoutRequestView.js +16 -5
  388. package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
  389. package/dist/features/seller/components/SellerProductShell.d.ts +16 -0
  390. package/dist/features/seller/components/SellerProductShell.js +123 -13
  391. package/dist/features/seller/components/SellerReviewsView.js +4 -2
  392. package/dist/features/seller/components/SellerSidebar.js +1 -1
  393. package/dist/features/seller/schemas/coupon-form.d.ts +26 -0
  394. package/dist/features/seller/schemas/coupon-form.js +27 -0
  395. package/dist/features/seller/schemas/product-form.d.ts +3 -0
  396. package/dist/features/seller/schemas/product-form.js +5 -0
  397. package/dist/features/shell/FormShell.js +2 -2
  398. package/dist/features/shell/QuickFormDrawer.js +14 -0
  399. package/dist/features/shell/SectionForm.d.ts +19 -0
  400. package/dist/features/shell/SectionForm.js +133 -9
  401. package/dist/features/shell/SectionForm.style.css +54 -0
  402. package/dist/features/shipments/components/AdminShipmentsView.js +16 -1
  403. package/dist/features/shipments/repository/shipment-items.repository.d.ts +9 -0
  404. package/dist/features/shipments/repository/shipment-items.repository.js +14 -0
  405. package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
  406. package/dist/features/sticker-trace/components/StickerCommitPanel.js +1 -1
  407. package/dist/features/store-extensions/schemas/report-review-form.d.ts +8 -8
  408. package/dist/features/stores/components/StoreGuideHubView.js +1 -1
  409. package/dist/features/stores/components/StoreHeader.js +1 -1
  410. package/dist/features/support/schemas/firestore.d.ts +73 -2
  411. package/dist/features/support/schemas/firestore.js +59 -0
  412. package/dist/index.d.ts +16 -24
  413. package/dist/index.js +38 -47
  414. package/dist/next/ErrorBoundary.js +1 -1
  415. package/dist/next/routing/route-map.d.ts +24 -0
  416. package/dist/next/routing/route-map.js +40 -0
  417. package/dist/providers/payment-manual/index.d.ts +15 -1
  418. package/dist/providers/payment-manual/index.js +37 -0
  419. package/dist/providers/payment-phonepe/index.d.ts +14 -1
  420. package/dist/providers/payment-phonepe/index.js +36 -0
  421. package/dist/providers/payment-razorpay/index.d.ts +44 -1
  422. package/dist/providers/payment-razorpay/index.js +99 -0
  423. package/dist/providers/shipping-shiprocket/index.d.ts +18 -0
  424. package/dist/providers/shipping-shiprocket/index.js +18 -0
  425. package/dist/schemas/registry.d.ts +44 -11
  426. package/dist/server-entry.d.ts +2 -0
  427. package/dist/server-entry.js +27 -0
  428. package/dist/server.d.ts +42 -0
  429. package/dist/server.js +93 -0
  430. package/dist/styles.css +418 -149
  431. package/dist/tailwind-utilities.css +1 -1
  432. package/dist/tokens/themes/default-dark.js +15 -12
  433. package/dist/tokens/themes/default-light.js +14 -11
  434. package/dist/tokens/tokens.css +106 -23
  435. package/dist/ui/DataTable.style.css +4 -4
  436. package/dist/ui/columns/cell-renderers.d.ts +20 -0
  437. package/dist/ui/columns/cell-renderers.js +26 -1
  438. package/dist/ui/columns/index.d.ts +1 -1
  439. package/dist/ui/columns/index.js +4 -1
  440. package/dist/ui/components/Badge.style.css +1 -1
  441. package/dist/ui/components/Breadcrumb.js +19 -1
  442. package/dist/ui/components/BulkActionBar.style.css +4 -4
  443. package/dist/ui/components/Button.style.css +1 -1
  444. package/dist/ui/components/Checkbox.style.css +1 -1
  445. package/dist/ui/components/FallbackShell.js +1 -1
  446. package/dist/ui/components/Form.d.ts +14 -1
  447. package/dist/ui/components/Form.js +2 -2
  448. package/dist/ui/components/FormField.js +18 -4
  449. package/dist/ui/components/FormField.style.css +43 -3
  450. package/dist/ui/components/GatedPrice.style.css +1 -1
  451. package/dist/ui/components/IconButton.style.css +1 -1
  452. package/dist/ui/components/Input.js +22 -1
  453. package/dist/ui/components/Input.style.css +38 -22
  454. package/dist/ui/components/ListingFilterDrawer.js +1 -1
  455. package/dist/ui/components/ListingToolbar.js +1 -1
  456. package/dist/ui/components/PaginatedSelect.js +0 -0
  457. package/dist/ui/components/Radio.style.css +1 -1
  458. package/dist/ui/components/Repeater.d.ts +53 -0
  459. package/dist/ui/components/Repeater.js +7 -0
  460. package/dist/ui/components/RichTextEditor.d.ts +20 -1
  461. package/dist/ui/components/RichTextEditor.js +23 -2
  462. package/dist/ui/components/Select.style.css +7 -21
  463. package/dist/ui/components/Semantic.js +27 -3
  464. package/dist/ui/components/TagInput.style.css +4 -9
  465. package/dist/ui/components/Textarea.style.css +4 -18
  466. package/dist/ui/components/Toggle.style.css +1 -1
  467. package/dist/ui/components/Typography.d.ts +3 -3
  468. package/dist/ui/components/Typography.js +15 -15
  469. package/dist/ui/components/ViewToggle.style.css +4 -4
  470. package/dist/ui/forms/AddAnotherToggle.d.ts +16 -0
  471. package/dist/ui/forms/AddAnotherToggle.js +56 -0
  472. package/dist/ui/forms/ColorPickerField.js +15 -2
  473. package/dist/ui/forms/FieldCheckbox.js +15 -2
  474. package/dist/ui/forms/FieldInput.d.ts +22 -1
  475. package/dist/ui/forms/FieldInput.js +19 -5
  476. package/dist/ui/forms/FieldLabel.d.ts +35 -0
  477. package/dist/ui/forms/FieldLabel.js +70 -0
  478. package/dist/ui/forms/FieldSelect.d.ts +4 -1
  479. package/dist/ui/forms/FieldSelect.js +27 -5
  480. package/dist/ui/forms/FieldTextarea.d.ts +4 -1
  481. package/dist/ui/forms/FieldTextarea.js +22 -5
  482. package/dist/ui/forms/FormShell.d.ts +17 -1
  483. package/dist/ui/forms/FormShell.js +36 -2
  484. package/dist/ui/forms/FormShell.style.css +41 -33
  485. package/dist/ui/forms/index.d.ts +5 -1
  486. package/dist/ui/forms/index.js +2 -0
  487. package/dist/ui/icons/icon-registry.d.ts +1 -0
  488. package/dist/ui/icons/icon-registry.js +17 -1
  489. package/dist/utils/id-generators.d.ts +80 -0
  490. package/dist/utils/id-generators.js +93 -0
  491. package/dist/utils/search-txt-builders.d.ts +12 -0
  492. package/dist/utils/search-txt-builders.js +17 -0
  493. package/package.json +1 -1
  494. package/scripts/seed-cli.mjs +106 -5
  495. package/dist/features/loyalty/api/admin/loyalty/grant/route.d.ts +0 -12
  496. package/dist/features/loyalty/api/admin/loyalty/grant/route.js +0 -38
  497. package/dist/features/loyalty/api/balance/route.d.ts +0 -12
  498. package/dist/features/loyalty/api/balance/route.js +0 -41
  499. package/dist/features/loyalty/api/earn/route.d.ts +0 -12
  500. package/dist/features/loyalty/api/earn/route.js +0 -38
  501. package/dist/features/loyalty/api/history/route.d.ts +0 -12
  502. package/dist/features/loyalty/api/history/route.js +0 -58
  503. package/dist/features/loyalty/api/redeem/route.d.ts +0 -12
  504. package/dist/features/loyalty/api/redeem/route.js +0 -38
  505. package/dist/features/loyalty/columns/index.d.ts +0 -17
  506. package/dist/features/loyalty/columns/index.js +0 -40
  507. package/dist/features/loyalty/components/CoinsDisplay.d.ts +0 -12
  508. package/dist/features/loyalty/components/CoinsDisplay.js +0 -10
  509. package/dist/features/loyalty/components/index.d.ts +0 -1
  510. package/dist/features/loyalty/components/index.js +0 -1
  511. package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +0 -4
  512. package/dist/features/loyalty/hooks/useLoyaltyBalance.js +0 -25
  513. package/dist/features/loyalty/index.d.ts +0 -6
  514. package/dist/features/loyalty/index.js +0 -6
  515. package/dist/features/loyalty/manifest.d.ts +0 -2
  516. package/dist/features/loyalty/manifest.js +0 -16
  517. package/dist/features/loyalty/messages/en.json +0 -19
  518. package/dist/features/loyalty/repository/loyalty.repository.d.ts +0 -8
  519. package/dist/features/loyalty/repository/loyalty.repository.js +0 -22
  520. package/dist/features/loyalty/schemas/index.d.ts +0 -85
  521. package/dist/features/loyalty/schemas/index.js +0 -40
  522. package/dist/features/loyalty/server.d.ts +0 -6
  523. package/dist/features/loyalty/server.js +0 -6
  524. package/dist/features/loyalty/types/index.d.ts +0 -31
  525. package/dist/features/loyalty/types/index.js +0 -1
  526. package/dist/features/loyalty/types/loyalty-config.d.ts +0 -7
  527. package/dist/features/loyalty/types/loyalty-config.js +0 -1
  528. package/dist/features/loyalty/types/loyalty-math.d.ts +0 -9
  529. package/dist/features/loyalty/types/loyalty-math.js +0 -27
  530. package/dist/features/products/components/ProductOwnerQuickActions.d.ts +0 -11
  531. package/dist/features/products/components/ProductOwnerQuickActions.js +0 -120
@@ -0,0 +1,197 @@
1
+ import type { BaseDocument } from "../../../_internal/shared/types/base-document";
2
+ export declare const STORAGE_BOXES_COLLECTION = "storageBoxes";
3
+ export declare const INVENTORY_PLACEMENTS_COLLECTION = "inventoryPlacements";
4
+ export declare const INVENTORY_MOVEMENTS_COLLECTION = "inventoryMovements";
5
+ /**
6
+ * The two box sizes actually owned.
7
+ *
8
+ * 🛑 A TS UNION, not a seeded reference list, and this was one of the plan's
9
+ * open questions. The deciding argument is that the LABEL GEOMETRY depends on
10
+ * it: a box label's dimensions are chosen per type, so a third type is a code
11
+ * change in the label profiles whatever the data model says. A seeded list
12
+ * would let an admin create an `AC90` that no label profile can print, and
13
+ * discover it at the printer.
14
+ *
15
+ * Adding a type is therefore deliberately a two-line code change plus a
16
+ * profile, not a form submission.
17
+ */
18
+ /**
19
+ * How many rows the receive station stages before it must commit.
20
+ *
21
+ * 🛑 THIS IS A FIRESTORE LIMIT, NOT A UI PREFERENCE. A transaction caps at 500
22
+ * writes and each received row is two of them (the placement and its movement
23
+ * row), so 50 rows is 100 writes with ample room for the ledger growing a
24
+ * field later. The whole table commits in ONE transaction because the operator
25
+ * has already physically filled the boxes — a partial write leaves the ledger
26
+ * disagreeing with the shelf and nothing saying which rows landed.
27
+ *
28
+ * 🛑 Declared here so the route and the station cannot disagree. It was a
29
+ * local `MAX_ROWS` in the route and a second literal in the view for one
30
+ * revision, which is the two-owners shape that drifts the moment either moves
31
+ * (Root Cause #42) — and the failure would be silent in the worst direction:
32
+ * a UI cap above the route's gives the operator a full table and a 400.
33
+ */
34
+ export declare const MAX_RECEIVE_ROWS = 50;
35
+ export declare const BoxTypeValues: readonly ["AC60", "AC30"];
36
+ export type BoxType = (typeof BoxTypeValues)[number];
37
+ /**
38
+ * `retired` rather than deleting: a box's movements are permanent, and a
39
+ * ledger row pointing at a box that no longer exists cannot be read back.
40
+ */
41
+ export declare const BoxStatusValues: readonly ["active", "full", "retired"];
42
+ export type BoxStatus = (typeof BoxStatusValues)[number];
43
+ /**
44
+ * Why stock moved. Every movement has one.
45
+ *
46
+ * `receive` inbound from a procurement shipment
47
+ * `move` box → box
48
+ * `pick` out of a box, for an order
49
+ * `adjust` a human reconciling a variance they investigated
50
+ * `audit` a count that AGREED — recorded so "last verified" is answerable
51
+ *
52
+ * 🛑 `pick` is MANUAL and does not auto-fire from checkout — the other open
53
+ * question in the plan. An automatic decrement would have the ledger assert a
54
+ * movement nobody performed: the stock is sold, but it is still in the box
55
+ * until someone walks over and takes it out. A ledger that records intentions
56
+ * rather than actions cannot be used to find a missing item, which is its
57
+ * only real job.
58
+ */
59
+ export declare const MovementKindValues: readonly ["receive", "move", "pick", "adjust", "audit"];
60
+ export type MovementKind = (typeof MovementKindValues)[number];
61
+ export interface StorageBoxDocument extends BaseDocument {
62
+ /**
63
+ * `AC60-03` — what is written on the physical label.
64
+ *
65
+ * 🛑 The id is `storagebox-{code}` and this is a PURE SLUG: a second
66
+ * `AC60-03` *is* the same box. A generated id would let two registry rows
67
+ * describe one physical object, and then "where is this" has two answers
68
+ * with no way to tell which shelf was meant.
69
+ */
70
+ code: string;
71
+ boxType: BoxType;
72
+ /** The number in the code, denormalised so a list can sort numerically. */
73
+ ordinal: number;
74
+ status: BoxStatus;
75
+ /** Free text — "shelf B, second from top". Deliberately not a taxonomy. */
76
+ location?: string;
77
+ /** "fits ~40 Burst tops" — a human's note, never a computed capacity. */
78
+ capacityNote?: string;
79
+ /**
80
+ * Rollups, for a list that does not fan out one read per box.
81
+ *
82
+ * 🛑 Maintained by a SCHEDULED REPAIR JOB, never a Firestore trigger. A
83
+ * trigger on a collection it also writes back to is Root Cause #92's exact
84
+ * shape — the one that cost 12M invocations against a 2M/month quota,
85
+ * because its no-op guard used `JSON.stringify` on a map whose key order
86
+ * Firestore does not preserve. A scheduled recompute cannot recurse.
87
+ *
88
+ * Treat as ADVISORY. `inventoryPlacements` is the truth; this is a cache.
89
+ */
90
+ rollup?: {
91
+ distinctProducts: number;
92
+ totalUnits: number;
93
+ computedAt: Date;
94
+ };
95
+ /** Word-prefix search tokens. Derived on write. */
96
+ searchTxt?: string[];
97
+ }
98
+ /**
99
+ * How many of one product are in one box, right now.
100
+ *
101
+ * 🛑 The id is DETERMINISTIC — `${boxId}__${productId}` — which makes "is X
102
+ * in Y" an O(1) document read and makes the write an idempotent upsert. With
103
+ * a generated id, the same question is a two-field query needing its own
104
+ * composite index, and a double-submit creates a second row for the same
105
+ * pair that silently doubles the count.
106
+ *
107
+ * `__` as the separator because both ids contain `-` (`storagebox-ac60-03`,
108
+ * `product-beyblade-x-dran-sword`), so a single hyphen could not be split
109
+ * back apart.
110
+ */
111
+ export interface InventoryPlacementDocument extends BaseDocument {
112
+ boxId: string;
113
+ productId: string;
114
+ /** Always ≥ 1. A zero placement is deleted — see the header. */
115
+ quantity: number;
116
+ /** "slot 4", "front left" — optional, free text, for a big box. */
117
+ slot?: string;
118
+ boxCode: string;
119
+ productTitle: string;
120
+ /** The human stock key at the time of placement — what is on the label. */
121
+ productSku?: string;
122
+ }
123
+ /**
124
+ * One movement. Append-only.
125
+ *
126
+ * 🛑 `quantity` IS ALWAYS POSITIVE. Direction is carried by `from`/`to`, not
127
+ * by the sign — a signed quantity means every reader has to agree on what a
128
+ * negative means, and the first one that disagrees double-counts. A `receive`
129
+ * has no `from`; a `pick` has no `to`; a `move` has both.
130
+ *
131
+ * Immutability is enforced by the repository overriding `update` and `delete`
132
+ * to throw, and by `audit-inventory-ledger-append-only`. A ledger that can be
133
+ * edited is a ledger nobody can use as evidence.
134
+ */
135
+ export interface InventoryMovementDocument extends BaseDocument {
136
+ kind: MovementKind;
137
+ productId: string;
138
+ /** Always positive. See the header. */
139
+ quantity: number;
140
+ /** Absent on `receive` — stock came from outside the system. */
141
+ fromBoxId?: string;
142
+ /** Absent on `pick` — stock left the system. */
143
+ toBoxId?: string;
144
+ /** When it physically happened, which is not always when it was recorded. */
145
+ occurredAt: Date;
146
+ /** Who did it. A uid, never a name — this collection is not PII-encrypted. */
147
+ actorUid: string;
148
+ /** Required on `adjust`: a variance nobody explained is not reconciled. */
149
+ reason?: string;
150
+ /** The procurement shipment a `receive` came from, when there was one. */
151
+ shipmentId?: string;
152
+ /** Denormalised for a readable ledger. Advisory, like the placement's. */
153
+ productTitle?: string;
154
+ fromBoxCode?: string;
155
+ toBoxCode?: string;
156
+ }
157
+ /**
158
+ * The deterministic placement id.
159
+ *
160
+ * One definition, used by the repository, the receive station and the seed —
161
+ * a second copy of this string concatenation is a second answer to "is X in
162
+ * Y", and the two would disagree the first time one of them changed.
163
+ */
164
+ export declare function placementId(boxId: string, productId: string): string;
165
+ /** Field-name constants, so a query never spells a path by hand. */
166
+ export declare const STORAGE_BOX_FIELDS: {
167
+ readonly CODE: "code";
168
+ readonly BOX_TYPE: "boxType";
169
+ readonly ORDINAL: "ordinal";
170
+ readonly STATUS: "status";
171
+ readonly LOCATION: "location";
172
+ readonly SEARCH_TXT: "searchTxt";
173
+ readonly CREATED_AT: "createdAt";
174
+ readonly UPDATED_AT: "updatedAt";
175
+ };
176
+ export declare const INVENTORY_PLACEMENT_FIELDS: {
177
+ readonly BOX_ID: "boxId";
178
+ readonly PRODUCT_ID: "productId";
179
+ readonly QUANTITY: "quantity";
180
+ readonly SLOT: "slot";
181
+ readonly BOX_CODE: "boxCode";
182
+ readonly PRODUCT_TITLE: "productTitle";
183
+ readonly PRODUCT_SKU: "productSku";
184
+ readonly CREATED_AT: "createdAt";
185
+ readonly UPDATED_AT: "updatedAt";
186
+ };
187
+ export declare const INVENTORY_MOVEMENT_FIELDS: {
188
+ readonly KIND: "kind";
189
+ readonly PRODUCT_ID: "productId";
190
+ readonly QUANTITY: "quantity";
191
+ readonly FROM_BOX_ID: "fromBoxId";
192
+ readonly TO_BOX_ID: "toBoxId";
193
+ readonly OCCURRED_AT: "occurredAt";
194
+ readonly ACTOR_UID: "actorUid";
195
+ readonly SHIPMENT_ID: "shipmentId";
196
+ readonly CREATED_AT: "createdAt";
197
+ };
@@ -0,0 +1,159 @@
1
+ /*
2
+ * WHY: Stock lives in physical AC60 and AC30 boxes with a label maker, and
3
+ * "where is this" is a question the catalogue could not answer. The
4
+ * previous attempt — `ProductDocument.physicalLocation`, a free-text
5
+ * zone/shelf/bin triple — carried 0 of 1,039 products and had no write
6
+ * path at all, because a location typed once and never moved is not an
7
+ * inventory system. A box registry plus an append-only move ledger is.
8
+ *
9
+ * WHAT: Three TOP-LEVEL collections.
10
+ *
11
+ * storageBoxes/{storagebox-slug} one physical box
12
+ * inventoryPlacements/{boxId__prodId} how many of X are in Y, right now
13
+ * inventoryMovements/{auto} every move, immutable
14
+ *
15
+ * ── 🛑 TOP-LEVEL, NOT SUBCOLLECTIONS, and the reason is structural ─────────
16
+ *
17
+ * `BaseRepository.getCollection()` returns a `CollectionReference` and every
18
+ * write method depends on it, while `collectionGroup()` returns a `Query`.
19
+ * Measured: the repo has 685 `COLLECTION` indexes, 3 `COLLECTION_GROUP`
20
+ * indexes, and **zero `collectionGroup(` call sites** — all three of those
21
+ * indexes are dead. A subcollection here would mean hand-rolling the
22
+ * repository base and losing PII encryption, `searchTxt` and `mapDoc` with it.
23
+ *
24
+ * ── 🛑 A ZERO-QUANTITY PLACEMENT IS DELETED, NEVER STORED AT ZERO ──────────
25
+ *
26
+ * Keeping zeros forces every "what is in this box" read to pair
27
+ * `quantity > 0` with an `orderBy`, and Firestore appends an inequality's
28
+ * field to the sort implicitly — so it demands a composite index in an order
29
+ * nobody declares, fails with FAILED_PRECONDITION, and every caller in this
30
+ * codebase wraps such a read in `.catch(() => null)`. That renders as an
31
+ * EMPTY BOX rather than an error (Root Cause #59). Absence means zero.
32
+ *
33
+ * ── 🛑 NO STOCK RECONCILIATION. `stockQuantity` STAYS AUTHORITATIVE ───────
34
+ *
35
+ * This system never writes it. Deriving it would write the left side of
36
+ * `resolveStockResync`'s invariant (`reserved = prevStock − prevAvailable`)
37
+ * from a measurement blind to reservations, handing reserved units back to
38
+ * the shelf. And a nightly reconciler would be Root Cause #102 verbatim: a
39
+ * three-way state (authored / reserved / located) against one number cannot
40
+ * distinguish "3 are lost" from "3 are on the photography table". Variance is
41
+ * a REPORT a human resolves with an `adjust` movement.
42
+ *
43
+ * EXPORTS: STORAGE_BOXES_COLLECTION, INVENTORY_PLACEMENTS_COLLECTION,
44
+ * INVENTORY_MOVEMENTS_COLLECTION, BoxTypeValues, BoxType, BoxStatusValues,
45
+ * BoxStatus, MovementKindValues, MovementKind, StorageBoxDocument,
46
+ * InventoryPlacementDocument, InventoryMovementDocument, placementId,
47
+ * STORAGE_BOX_FIELDS, INVENTORY_PLACEMENT_FIELDS, INVENTORY_MOVEMENT_FIELDS
48
+ *
49
+ * @tag domain:inventory
50
+ * @tag layer:feature
51
+ * @tag pattern:firestore-schema
52
+ * @tag access:server
53
+ * @tag sideEffects:none
54
+ */
55
+ export const STORAGE_BOXES_COLLECTION = "storageBoxes";
56
+ export const INVENTORY_PLACEMENTS_COLLECTION = "inventoryPlacements";
57
+ export const INVENTORY_MOVEMENTS_COLLECTION = "inventoryMovements";
58
+ /**
59
+ * The two box sizes actually owned.
60
+ *
61
+ * 🛑 A TS UNION, not a seeded reference list, and this was one of the plan's
62
+ * open questions. The deciding argument is that the LABEL GEOMETRY depends on
63
+ * it: a box label's dimensions are chosen per type, so a third type is a code
64
+ * change in the label profiles whatever the data model says. A seeded list
65
+ * would let an admin create an `AC90` that no label profile can print, and
66
+ * discover it at the printer.
67
+ *
68
+ * Adding a type is therefore deliberately a two-line code change plus a
69
+ * profile, not a form submission.
70
+ */
71
+ /**
72
+ * How many rows the receive station stages before it must commit.
73
+ *
74
+ * 🛑 THIS IS A FIRESTORE LIMIT, NOT A UI PREFERENCE. A transaction caps at 500
75
+ * writes and each received row is two of them (the placement and its movement
76
+ * row), so 50 rows is 100 writes with ample room for the ledger growing a
77
+ * field later. The whole table commits in ONE transaction because the operator
78
+ * has already physically filled the boxes — a partial write leaves the ledger
79
+ * disagreeing with the shelf and nothing saying which rows landed.
80
+ *
81
+ * 🛑 Declared here so the route and the station cannot disagree. It was a
82
+ * local `MAX_ROWS` in the route and a second literal in the view for one
83
+ * revision, which is the two-owners shape that drifts the moment either moves
84
+ * (Root Cause #42) — and the failure would be silent in the worst direction:
85
+ * a UI cap above the route's gives the operator a full table and a 400.
86
+ */
87
+ export const MAX_RECEIVE_ROWS = 50;
88
+ export const BoxTypeValues = ["AC60", "AC30"];
89
+ /**
90
+ * `retired` rather than deleting: a box's movements are permanent, and a
91
+ * ledger row pointing at a box that no longer exists cannot be read back.
92
+ */
93
+ export const BoxStatusValues = ["active", "full", "retired"];
94
+ /**
95
+ * Why stock moved. Every movement has one.
96
+ *
97
+ * `receive` inbound from a procurement shipment
98
+ * `move` box → box
99
+ * `pick` out of a box, for an order
100
+ * `adjust` a human reconciling a variance they investigated
101
+ * `audit` a count that AGREED — recorded so "last verified" is answerable
102
+ *
103
+ * 🛑 `pick` is MANUAL and does not auto-fire from checkout — the other open
104
+ * question in the plan. An automatic decrement would have the ledger assert a
105
+ * movement nobody performed: the stock is sold, but it is still in the box
106
+ * until someone walks over and takes it out. A ledger that records intentions
107
+ * rather than actions cannot be used to find a missing item, which is its
108
+ * only real job.
109
+ */
110
+ export const MovementKindValues = [
111
+ "receive",
112
+ "move",
113
+ "pick",
114
+ "adjust",
115
+ "audit",
116
+ ];
117
+ /**
118
+ * The deterministic placement id.
119
+ *
120
+ * One definition, used by the repository, the receive station and the seed —
121
+ * a second copy of this string concatenation is a second answer to "is X in
122
+ * Y", and the two would disagree the first time one of them changed.
123
+ */
124
+ export function placementId(boxId, productId) {
125
+ return `${boxId}__${productId}`;
126
+ }
127
+ /** Field-name constants, so a query never spells a path by hand. */
128
+ export const STORAGE_BOX_FIELDS = {
129
+ CODE: "code",
130
+ BOX_TYPE: "boxType",
131
+ ORDINAL: "ordinal",
132
+ STATUS: "status",
133
+ LOCATION: "location",
134
+ SEARCH_TXT: "searchTxt",
135
+ CREATED_AT: "createdAt",
136
+ UPDATED_AT: "updatedAt",
137
+ };
138
+ export const INVENTORY_PLACEMENT_FIELDS = {
139
+ BOX_ID: "boxId",
140
+ PRODUCT_ID: "productId",
141
+ QUANTITY: "quantity",
142
+ SLOT: "slot",
143
+ BOX_CODE: "boxCode",
144
+ PRODUCT_TITLE: "productTitle",
145
+ PRODUCT_SKU: "productSku",
146
+ CREATED_AT: "createdAt",
147
+ UPDATED_AT: "updatedAt",
148
+ };
149
+ export const INVENTORY_MOVEMENT_FIELDS = {
150
+ KIND: "kind",
151
+ PRODUCT_ID: "productId",
152
+ QUANTITY: "quantity",
153
+ FROM_BOX_ID: "fromBoxId",
154
+ TO_BOX_ID: "toBoxId",
155
+ OCCURRED_AT: "occurredAt",
156
+ ACTOR_UID: "actorUid",
157
+ SHIPMENT_ID: "shipmentId",
158
+ CREATED_AT: "createdAt",
159
+ };
@@ -59,6 +59,17 @@ export interface AppLayoutShellProps {
59
59
  homeHref: string;
60
60
  shopHref: string;
61
61
  footer: FooterLayoutProps;
62
+ /**
63
+ * Render the public marketing footer. Defaults to `true`.
64
+ *
65
+ * Pass `false` on a dashboard. `footer` stays REQUIRED either way, so the
66
+ * consumer keeps one code path and there is no "which half did I forget"
67
+ * state — this only decides whether it is shown.
68
+ *
69
+ * 🛑 It also moves the bottom-chrome reservation: the footer owns it when
70
+ * rendered, `<Main>` owns it when not. See the comment on `<Main>`.
71
+ */
72
+ showFooter?: boolean;
62
73
  searchSlot?: React.ReactNode;
63
74
  /** Render-prop alternative to searchSlot — receives onClose so the slot can close the overlay. */
64
75
  searchSlotRenderer?: (onClose: () => void) => React.ReactNode;
@@ -137,4 +148,4 @@ export interface AppLayoutShellProps {
137
148
  };
138
149
  };
139
150
  }
140
- export declare function AppLayoutShell({ children, navItems, sidebarItems, sidebarSections, sidebarPrimaryActions, sidebarTitle, hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle, suppressDashboardNav, hideSidebarToggle, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, eventBannerSlot, showBottomNav, contentClassName, lightBackground, darkBackground, }: AppLayoutShellProps): React.JSX.Element;
151
+ export declare function AppLayoutShell({ children, navItems, sidebarItems, sidebarSections, sidebarPrimaryActions, sidebarTitle, hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, showFooter, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle, suppressDashboardNav, hideSidebarToggle, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, eventBannerSlot, showBottomNav, contentClassName, lightBackground, darkBackground, }: AppLayoutShellProps): React.JSX.Element;
@@ -120,7 +120,7 @@ function CollapsibleSidebarSection({ section, navItemClass, navItemActiveClass,
120
120
  return (_jsxs(Stack, { gap: "none", className: "", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center justify-between px-[var(--appkit-space-1)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-semibold uppercase tracking-wider text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text-muted)] transition-colors", children: [_jsx(Span, { children: section.title }), _jsx("svg", { className: `w-3.5 h-3.5 transition-transform duration-200 ${open ? "rotate-180" : ""} shrink-0`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(SidebarSectionLinks, { items: section.items, activeHref: activeHref, activeItem: activeItem, navItemClass: navItemClass, navItemActiveClass: navItemActiveClass }))] }));
121
121
  }
122
122
  /** Sidebar header when a user is logged in — avatar + display name + close button. */
123
- function SidebarUserHeader({ user, onClose, }) {
123
+ function SidebarUserHeader({ user, onClose, profileHref, }) {
124
124
  return (_jsxs(Row, { align: "center", justify: "between", gap: "3", children: [_jsxs(Row, { className: "flex-1 min-w-0", align: "center", gap: "3", children: [_jsxs(Div, { className: "flex-shrink-0 relative", children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata
125
125
  ? {
126
126
  url: user.avatarMetadata.url,
@@ -129,11 +129,11 @@ function SidebarUserHeader({ user, onClose, }) {
129
129
  }
130
130
  : user.photoURL
131
131
  ? { url: user.photoURL, position: { x: 50, y: 50 }, zoom: 1 }
132
- : null, size: "md", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && !isBuyerUser(user) && (_jsx(Row, { textWeight: "bold", className: `absolute -bottom-0.5 -right-0.5 w-4 h-4 border-2 border-white text-white text-[9px] leading-none select-none ${ROLE_DOT_BG_CLASS[user.role] ?? "bg-[var(--appkit-color-text-muted)]"}`, align: "center", justify: "center", rounded: "full", title: user.role.charAt(0).toUpperCase() + user.role.slice(1), "aria-label": user.role, children: user.role.charAt(0).toUpperCase() }))] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", color: "primary", size: "sm", weight: "medium", children: user.displayName || "User" }), _jsx(Text, { className: "truncate", color: "muted", size: "xs", children: user.email || "" })] })] }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "flex-shrink-0 rounded-full p-[var(--appkit-space-2)] text-[var(--appkit-color-text-muted)] hover:bg-surface-hover hover:text-zinc-900 text-[var(--appkit-color-text-muted)] dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
132
+ : null, size: "md", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && !isBuyerUser(user) && (_jsx(Row, { textWeight: "bold", className: `absolute -bottom-0.5 -right-0.5 w-4 h-4 border-2 border-white text-white text-[9px] leading-none select-none ${ROLE_DOT_BG_CLASS[user.role] ?? "bg-[var(--appkit-color-text-muted)]"}`, align: "center", justify: "center", rounded: "full", title: user.role.charAt(0).toUpperCase() + user.role.slice(1), "aria-label": user.role, children: user.role.charAt(0).toUpperCase() })), profileHref && (_jsx(TextLink, { href: profileHref, variant: "none", onClick: onClose, className: "absolute inset-0 rounded-full", children: _jsx(Span, { className: "sr-only", children: "View your profile" }) }))] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", color: "primary", size: "sm", weight: "medium", children: user.displayName || "User" }), _jsx(Text, { className: "truncate", color: "muted", size: "xs", children: user.email || "" })] })] }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "flex-shrink-0 rounded-full p-[var(--appkit-space-2)] hover:bg-surface-hover hover:text-zinc-900 text-[var(--appkit-color-text-muted)] dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
133
133
  }
134
134
  /** Sidebar header when no user is logged in — title + close button. */
135
135
  function SidebarGuestHeader({ sidebarTitle, onClose, }) {
136
- return (_jsxs(Row, { align: "center", justify: "between", children: [_jsx(Div, { textWeight: "semibold", textSize: "sm", color: "primary", children: sidebarTitle }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "rounded-full p-[var(--appkit-space-2)] text-[var(--appkit-color-text-muted)] hover:bg-surface-hover hover:text-zinc-900 text-[var(--appkit-color-text-muted)] dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
136
+ return (_jsxs(Row, { align: "center", justify: "between", children: [_jsx(Div, { textWeight: "semibold", textSize: "sm", color: "primary", children: sidebarTitle }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "rounded-full p-[var(--appkit-space-2)] hover:bg-surface-hover hover:text-zinc-900 text-[var(--appkit-color-text-muted)] dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
137
137
  }
138
138
  function SidebarContent({ sidebarItems, sidebarSections, sidebarPrimaryActions, user, activeHref, profileHref, userOrdersHref, userWishlistHref, userSettingsHref, adminHref, storeHref, sellerHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, theme, activeThemeName, toggleTheme, onLogout, onAfterLogout, }) {
139
139
  const hasLegacyItems = sidebarItems.length > 0;
@@ -177,10 +177,10 @@ function SidebarContent({ sidebarItems, sidebarSections, sidebarPrimaryActions,
177
177
  action.variant === "outline"
178
178
  ? "border hover:bg-surface-hover border-[var(--appkit-color-border)] text-[var(--appkit-color-text)]"
179
179
  : "bg-primary text-white hover:bg-primary-600 dark:bg-primary dark:hover:bg-primary-600 btn-glow",
180
- ].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, hasActive: !!activeProfileLink, children: _jsxs(Ul, { spacing: "2xs", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: activeProfileLink?.href === profileHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === profileHref ? "page" : undefined, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: activeProfileLink?.href === userOrdersHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userOrdersHref ? "page" : undefined, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: activeProfileLink?.href === userWishlistHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userWishlistHref ? "page" : undefined, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: activeProfileLink?.href === userSettingsHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userSettingsHref ? "page" : undefined, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { layout: "grid", gap: "2", className: "grid-cols-2", children: [user.stats.totalOrders != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.totalOrders }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.reviewsCount }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Reviews" })] })), user.stats.auctionsWon != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.auctionsWon }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Auctions Won" })] })), user.stats.itemsSold != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.itemsSold }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, hasActive: !!activeDashboardLink, children: _jsxs(Ul, { spacing: "2xs", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: activeDashboardLink?.href === adminHref ? navItemActiveClass : navItemClass, "aria-current": activeDashboardLink?.href === adminHref ? "page" : undefined, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: activeDashboardLink?.href === resolvedStoreHref ? navItemActiveClass : navItemClass, "aria-current": activeDashboardLink?.href === resolvedStoreHref ? "page" : undefined, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass, navItemActiveClass: navItemActiveClass, activeHref: activeHref }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot || showThemeToggleInSidebar || (isAuthenticated && onLogout)) && (_jsxs(Stack, { border: "default", className: "border-t border-[var(--appkit-color-border-subtle)]", padding: "t-md", gap: "3", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center justify-end gap-[var(--appkit-space-3)] rounded-lg px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text-muted)] transition-colors hover:bg-primary-surface hover:text-primary-800 dark:hover:text-primary-200", children: [_jsx(Span, { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), activeThemeName] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => { onLogout(); onAfterLogout(); }, className: CLS_LOGOUT_BTN, children: labels.logout }))] }))] }));
180
+ ].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, hasActive: !!activeProfileLink, children: _jsxs(Ul, { spacing: "2xs", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: activeProfileLink?.href === profileHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === profileHref ? "page" : undefined, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: activeProfileLink?.href === userOrdersHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userOrdersHref ? "page" : undefined, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: activeProfileLink?.href === userWishlistHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userWishlistHref ? "page" : undefined, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: activeProfileLink?.href === userSettingsHref ? navItemActiveClass : navItemClass, "aria-current": activeProfileLink?.href === userSettingsHref ? "page" : undefined, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { layout: "grid", gap: "2", className: "grid-cols-2", children: [user.stats.totalOrders != null && userOrdersHref && (_jsxs(TextLink, { href: userOrdersHref, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.totalOrders }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(TextLink, { href: `${profileHref}#reviews`, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.reviewsCount }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Reviews" })] })), user.stats.auctionsWon != null && userOrdersHref && (_jsxs(TextLink, { href: `${userOrdersHref}?orderType=auction`, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.auctionsWon }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Auctions Won" })] })), user.stats.itemsSold != null && resolvedStoreHref && (_jsxs(TextLink, { href: resolvedStoreHref, variant: "none", className: CLS_STAT_BOX, children: [_jsx(Text, { className: "leading-none", color: "primary", size: "lg", weight: "bold", children: user.stats.itemsSold }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, hasActive: !!activeDashboardLink, children: _jsxs(Ul, { spacing: "2xs", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: activeDashboardLink?.href === adminHref ? navItemActiveClass : navItemClass, "aria-current": activeDashboardLink?.href === adminHref ? "page" : undefined, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: activeDashboardLink?.href === resolvedStoreHref ? navItemActiveClass : navItemClass, "aria-current": activeDashboardLink?.href === resolvedStoreHref ? "page" : undefined, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass, navItemActiveClass: navItemActiveClass, activeHref: activeHref }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot || showThemeToggleInSidebar || (isAuthenticated && onLogout)) && (_jsxs(Stack, { border: "default", className: "border-t border-[var(--appkit-color-border-subtle)]", padding: "t-md", gap: "3", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center justify-end gap-[var(--appkit-space-3)] rounded-lg px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text-muted)] transition-colors hover:bg-primary-surface hover:text-primary-800 dark:hover:text-primary-200", children: [_jsx(Span, { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), activeThemeName] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => { onLogout(); onAfterLogout(); }, className: CLS_LOGOUT_BTN, children: labels.logout }))] }))] }));
181
181
  }
182
182
  // ─── Main component ────────────────────────────────────────────────────────────
183
- export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, showBottomNav = true, contentClassName, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
183
+ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, messagesHref, unreadMessageCount, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, showFooter = true, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, showBottomNav = true, contentClassName, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
184
184
  // QueryClientProvider used to be created here so AppLayoutShell could stand
185
185
  // alone. The real cause of the 2026-06-10/11 "No QueryClient set" prod crash
186
186
  // turned out to be a peer-dep duplicate of @tanstack/query-core under
@@ -247,12 +247,18 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
247
247
  opacity: darkBackground.overlay?.opacity ?? 0,
248
248
  },
249
249
  };
250
- return (_jsx(_Fragment, { children: _jsxs(Stack, { className: "min-h-screen w-full overflow-x-clip transition-colors duration-300", children: [_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: normalizedLightBackground, darkMode: normalizedDarkBackground }), _jsx(Div, { id: TOP_BANNER_SLOT_ID, className: "w-full" }), _jsxs(Div, { ref: headerRef, className: "sticky top-0 z-50 w-full", children: [_jsx(TitleBar, { onToggleSidebar: handleTogglePublicSidebar, sidebarOpen: sidebarOpen, onSearchToggle: () => setSearchOpen((prev) => !prev), searchOpen: searchOpen, brandName: brandName, brandShortName: brandShortName, siteLogoUrl: siteLogoUrl, logoHref: logoHref, promotionsHref: promotionsHref, cartHref: cartHref, wishlistHref: wishlistHref, messagesHref: messagesHref, unreadMessageCount: unreadMessageCount, userId: userId, profileHref: profileHref, loginHref: loginHref, registerHref: registerHref, user: user, navSlot: titleBarNavSlot, notificationSlot: titleBarNotificationSlot, devSlot: titleBarDevSlot, promoStripText: titleBarPromoStripText, isDark: theme === "dark", onToggleTheme: showThemeToggle ? toggleTheme : undefined, onBeforeToggleDashboardNav: handleBeforeDashboardNavToggle, suppressDashboardNav: suppressDashboardNav, hideSidebarToggle: hideSidebarToggle }), _jsx(NavbarWithSettings, { navItems: navItems, hiddenNavItems: hiddenNavItems, permissions: authUser?.permissions }), searchOpen && (searchSlotRenderer ? searchSlotRenderer(() => setSearchOpen(false)) : searchSlot), eventBannerSlot] }), _jsx(AutoBreadcrumbs, {}), _jsxs(Div, { layout: "flex", className: "relative w-full flex-1 overflow-x-clip", children: [_jsx(SidebarLayout, { isOpen: sidebarOpen, ariaLabel: "Secondary navigation", header: user ? (_jsx(SidebarUserHeader, { user: user, onClose: () => setSidebarOpen(false) })) : (_jsx(SidebarGuestHeader, { sidebarTitle: sidebarTitle, onClose: () => setSidebarOpen(false) })), onClose: () => setSidebarOpen(false), children: sidebarContent }), _jsx(Main, { id: "main-content",
251
- // No bottom-chrome clearance here on purpose. FooterLayout is a
252
- // SIBLING rendered after <Main>, so a margin here only gaps
253
- // main-to-footer — it never clears the bottom of the page, which is
254
- // what the fixed nav + tier actually overlap. That reservation now
255
- // lives on the footer's own padding-bottom.
250
+ return (_jsx(_Fragment, { children: _jsxs(Stack, { className: "min-h-screen w-full overflow-x-clip transition-colors duration-300", children: [_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: normalizedLightBackground, darkMode: normalizedDarkBackground }), _jsx(Div, { id: TOP_BANNER_SLOT_ID, className: "w-full" }), _jsxs(Div, { ref: headerRef, className: "sticky top-0 z-50 w-full", children: [_jsx(TitleBar, { onToggleSidebar: handleTogglePublicSidebar, sidebarOpen: sidebarOpen, onSearchToggle: () => setSearchOpen((prev) => !prev), searchOpen: searchOpen, brandName: brandName, brandShortName: brandShortName, siteLogoUrl: siteLogoUrl, logoHref: logoHref, promotionsHref: promotionsHref, cartHref: cartHref, wishlistHref: wishlistHref, messagesHref: messagesHref, unreadMessageCount: unreadMessageCount, userId: userId, profileHref: profileHref, loginHref: loginHref, registerHref: registerHref, user: user, navSlot: titleBarNavSlot, notificationSlot: titleBarNotificationSlot, devSlot: titleBarDevSlot, promoStripText: titleBarPromoStripText, isDark: theme === "dark", onToggleTheme: showThemeToggle ? toggleTheme : undefined, onBeforeToggleDashboardNav: handleBeforeDashboardNavToggle, suppressDashboardNav: suppressDashboardNav, hideSidebarToggle: hideSidebarToggle }), _jsx(NavbarWithSettings, { navItems: navItems, hiddenNavItems: hiddenNavItems, permissions: authUser?.permissions }), searchOpen && (searchSlotRenderer ? searchSlotRenderer(() => setSearchOpen(false)) : searchSlot), eventBannerSlot] }), _jsx(AutoBreadcrumbs, {}), _jsxs(Div, { layout: "flex", className: "relative w-full flex-1 overflow-x-clip", children: [_jsx(SidebarLayout, { isOpen: sidebarOpen, ariaLabel: "Secondary navigation", header: user ? (_jsx(SidebarUserHeader, { user: user, onClose: () => setSidebarOpen(false), profileHref: profileHref })) : (_jsx(SidebarGuestHeader, { sidebarTitle: sidebarTitle, onClose: () => setSidebarOpen(false) })), onClose: () => setSidebarOpen(false), children: sidebarContent }), _jsx(Main, { id: "main-content",
251
+ // Bottom-chrome clearance belongs to whichever element is LAST.
252
+ //
253
+ // With the footer rendered it is the footer's, and a margin here
254
+ // would only gap main-to-footer — it would never clear the bottom
255
+ // of the page, which is what the fixed nav + tier actually
256
+ // overlap. That is why this carried no bottom padding.
257
+ //
258
+ // With the footer SUPPRESSED (`showFooter={false}`, which is every
259
+ // dashboard page) `<Main>` becomes the last element, so the same
260
+ // reasoning puts the reservation here instead. Exactly one of the
261
+ // two owns it at a time; both would add a screen of dead space.
256
262
  //
257
263
  // The TOP tier is the mirror image and does belong here: at `lg` the
258
264
  // chrome tier hangs under the header as a fixed bar, so without this
@@ -260,5 +266,12 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
260
266
  // is 0 below `lg` and 0 whenever no bar is published, so this
261
267
  // reserves exactly nothing until there is something to reserve —
262
268
  // which is why it can be unconditional rather than route-gated.
263
- className: "w-full flex-1 flex flex-col pt-[var(--top-chrome-height,0px)] transition-[padding-top] duration-300 ease-out", children: _jsx(Div, { padding: "y-lg", className: `flex-1 ${contentClassName ?? "mx-auto w-full max-w-screen-xl px-[var(--appkit-space-5)] md:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)]"}`, children: children }) })] }), _jsx(BackToTop, {}), _jsx(FooterLayout, { ...footer }), _jsx(BottomChrome, { children: _jsx(BottomActions, {}) }), _jsx(SideActionDock, {}), showBottomNav && (_jsx(BottomNavbar, { user: user, userId: userId, homeHref: homeHref, shopHref: shopHref, cartHref: cartHref, wishlistHref: wishlistHref, profileHref: profileHref, loginHref: loginHref, onSearchToggle: () => setSearchOpen((prev) => !prev), navItems: navItems, onMoreToggle: handleTogglePublicSidebar })), _jsx(UnsavedChangesModal, {})] }) }));
269
+ className: [
270
+ "w-full flex-1 flex flex-col pt-[var(--top-chrome-height,0px)] transition-[padding-top] duration-300 ease-out",
271
+ showFooter
272
+ ? ""
273
+ : "pb-[calc(var(--bottom-nav-height,4rem)+var(--bottom-chrome-height,0px))]",
274
+ ]
275
+ .filter(Boolean)
276
+ .join(" "), children: _jsx(Div, { padding: contentClassName ? "none" : "y-lg", className: `flex-1 ${contentClassName ?? "mx-auto w-full max-w-screen-xl px-[var(--appkit-space-5)] md:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)]"}`, children: children }) })] }), _jsx(BackToTop, {}), showFooter && _jsx(FooterLayout, { ...footer }), _jsx(BottomChrome, { children: _jsx(BottomActions, {}) }), _jsx(SideActionDock, {}), showBottomNav && (_jsx(BottomNavbar, { user: user, userId: userId, homeHref: homeHref, shopHref: shopHref, cartHref: cartHref, wishlistHref: wishlistHref, profileHref: profileHref, loginHref: loginHref, onSearchToggle: () => setSearchOpen((prev) => !prev), navItems: navItems, onMoreToggle: handleTogglePublicSidebar })), _jsx(UnsavedChangesModal, {})] }) }));
264
277
  }